2013-04-20 10 views
7

Tôi đang cố gắng viết một hàm sẽ cung cấp cho tôi một mẫu sổ tay được biên dịch (tôi có tất cả các mẫu trong các tệp riêng biệt) bằng cách sử dụng cuộc gọi ajax để lấy mẫu và biên dịch nó để sử dụng, nhưng tôi cần để sử dụng lời hứa để tôi có thể sử dụng nó.tải handlebars mẫu không đồng bộ

function getTemplate(name){ 
    $.get('/'+name+'.hbs').success(function(src){ 
     var template = Handlebars.compile(src); 
     //can't return the template here. 
    }); 
} 

Làm thế nào để làm điều này với lời hứa để tôi có thể làm điều gì đó như:

$("a").click(function(e){ 
    getTemplate('form').done(function(template){ 
     $("body").append(template({ 
       name: "My Name" 
      }) 
     ); 
    }); 
}); 
+0

Có thể liên quan: http://stackoverflow.com/questions/133310/how-can-i-get-jquery-to-perform-a-synchronous- thay vì-không-đồng bộ-ajax-re – ubik

+0

@PedroFerreira 'async: false' bị phản đối và là một giải pháp khủng khiếp – charlietfl

+0

@charlietfl Có, tôi đồng ý. Nhưng nó vẫn có thể thú vị như một lựa chọn, trong trường hợp cụ thể. – ubik

Trả lời

16

Chovy, tôi thấy bạn đã chấp nhận một câu trả lời nhưng bạn có thể quan tâm để biết rằng getTemplate có thể, bằng cách kết nối .then() hơn .success(), được viết gần như trong câu hỏi :

function getTemplate(name) { 
    return $.get('/'+name+'.hbs').then(function(src) { 
     return Handlebars.compile(src); 
    }); 
} 

hoặc, chấp nhận ý tưởng của charlietfl để chuyển vào dữ liệu và trả về một Lời hứa của một đoạn bao gồm đầy đủ:

function getTemplate(name, data) { 
    return $.get('/'+name+'.hbs').then(function(src) { 
     return Handlebars.compile(src)(data); 
    }); 
} 

Hiệu quả nett là giống hệt với phiên bản charlietfl của getTemplate nhưng .then() làm cho nó không cần thiết để tạo ra một thu nhập hoãn lại một cách rõ ràng. Do đó, mã nhỏ gọn hơn.

+1

+1 @Beettroot sạch hơn giải pháp của tôi – charlietfl

+0

Cảm ơn bạn đã chấp nhận Chovy, mặc dù tôi cảm thấy mình đã đánh cắp đại diện Charlie: - | –

+0

Đừng quên rằng ajax là không đồng bộ và bạn có lẽ nên sử dụng một cuộc gọi lại trong chức năng đó để đảm bảo bạn không có vấn đề. Được sử dụng mã này và đã có vấn đề này chính xác – sMyles

4

Tiếp theo thêm một cuộc tranh luận dữ liệu vào getTemplate chức năng cũng như mẫu tên.

$(function(){ 
    var postData={title: "My New Post", content: "This is my first post!"}; 
getTemplate('template-1',postData).done(function(data){ 
    $('body').append(data) 
}) 
}); 

function getTemplate(name,data){ 
    var d=$.Deferred(); 

    $.get(name+'.html',function(response){ 

    var template = Handlebars.compile(response); 
    d.resolve(template(data)) 
    }); 

    return d.promise(); 

} 

DEMO

1

Tôi tạo ra một thư viện để giúp đỡ với loại vấn đề, kiểm tra tại github

Bạn chỉ cần thêm này để xem ứng dụng chính của bạn:

<script type="text/x-handlebars" data-template-name="application"> 
    <!-- Your HTML code --> 
    <div class="container"> 
     <div class="modal fade" id="editView" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true"> 
      <div class="modal-dialog"> 
       <div class="modal-content"> 
        {{view MainApp.ModalContainerView elementId="modalContainerView"}} 
       </div><!-- /.modal-content --> 
      </div><!-- /.modal-dialog --> 
     </div><!-- modal edit dialog --> 
     {{view MainApp.AppContainerView elementId="appContainerView"}} 
     {{outlet}} 
    </div> <!-- main container --> 
</script> 

đặt này vào MainApp bạn

Ví dụ:
var MainApp = Em.Application.create({ 
    LOG_TRANSITIONS: true, 
    ready: function() { 
    /** your code **/ 
    MainApp.AppContainerView = Em.ContainerView.extend({}); 
    MainApp.ModalContainerView = Em.ContainerView.extend({}); 
    /** And other containerView if you need for sections in tabs **/ 
    }); 

và ví dụ, để mở một phương thức có mẫu mà bạn muốn, bạn chỉ phải:

FactoryController.loadModalTemplate(templateName, callback); 

Và không quên thêm FactoryController và RepositoryController