简体   繁体   English

如何将车把与骨干集成

[英]How can I integrate handlebars with backbone

I have a simple single page application which is for my own learning.我有一个简单的单页应用程序,供我自己学习。 The page has a UL of all the services that I provide.该页面具有我提供的所有服务的 UL。 This list comes from a JSON.此列表来自 JSON。 Next to each service there is a price for it, and a check-box which the user can select if he needs the service.每项服务旁边都有一个价格,以及一个复选框,如果用户需要该服务,可以选择该复选框。

Under the list there is a total price value for all the services selected.在列表下有所有选定服务的总价。 Based on this, can you please tell me what wrong am I doing?基于此,你能告诉我我做错了什么吗? I am trying to integrate the list of services as a handlebar template.我正在尝试将服务列表集成为把手模板。 Here is the HTML这是 HTML

<head>
    <meta charset="utf-8" />
    <title>Your first Backbone.js App | Tutorialzine </title>

    <!-- Google web fonts -->
    <link href="http://fonts.googleapis.com/css?family=PT+Sans:400,700" rel='stylesheet' />

    <!-- The main CSS file -->
    <link href="http://localhost/backbone-demo/assets/css/style.css" rel="stylesheet" />

</head>

<body>

    <form id="main" method="post" action="submit.php">
        <h1>My Services</h1>
        <div id="serviceTable"></div>
            <ul id="services">              
        <script id="services-template" type="text/x-handlebars-template">
          <!-- The services will be inserted here via handlebars-->

          {{#each services}}
          <li>
              <input type="checkbox" value="1" name="{{title}}"/> {{title}}
              <span>${{price}} </span>
          </li>
          {{/each}}

        </script>
            </ul>

        <p id="total">total: <span>$0</span></p>

        <input type="submit" id="order" value="Order" />

    </form>



    <!-- JavaScript Includes -->
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
    <script src="http://localhost/backbone-demo/assets/js/libs/underscore.min.js"></script>
    <script src="http://localhost/backbone-demo/assets/js/libs/backbone.min.js"></script>
    <script src="http://localhost/backbone-demo/assets/js/libs/handlebars.js"></script>
    <script src="http://localhost/backbone-demo/assets/js/script.js"></script>
</body>

Here is the Javascript:这是Javascript:

$(function(){

// Create a model for the services
var Service = Backbone.Model.extend({

    // Will contain three attributes.
    // These are their default values

    defaults:{
        title: 'My service',
        price: 100,
        checked: false
    },

    // Helper function for checking/unchecking a service
    toggle: function(){
        this.set('checked', !this.get('checked'));
    }
});


// Create a collection of services
var ServiceList = Backbone.Collection.extend({

    // Will hold objects of the Service model
    model: Service,

    // Return an array only with the checked services
    getChecked: function(){         
        return this.where({checked:true});
    }
});

//Retrieve the list of services
$.ajax({
    type: "GET",
    url: "assets/services.json",
    async: true,
    success: function(response){
        // Prefill the collection with a number of services.            
        var services = new ServiceList(response);                   
        var ServiceView = Backbone.View.extend({
            tagName: 'li',

            events:{
                'click': 'toggleService'
            },

            initialize: function(){

                // Set up event listeners. The change backbone event
                // is raised when a property changes (like the checked field)                   
                this.listenTo(services, 'change', this.render);
            },

            render: function(){
                var tpl = Handlebars.compile($("#services-template").html());
                //console.log(this.$el.selector);
                this.$el.html(tpl({services: services.toJSON()}));
                //console.log(this.$el);
                $('#serviceTable').append(this.$el);

                //document.getElementById('serviceTable').innerHTML = serviceData;
                // Create the HTML                  
                /* this.$el.html('<input type="checkbox" value="1" name="' + this.model.get('title') + '" /> ' + this.model.get('title') + '<span>$' + this.model.get('price') + '</span>');
                this.$('input').prop('checked', this.model.get('checked')); */

                // Returning the object is a good practice
                // that makes chaining possible
                return this;
            },

            toggleService: function(){
                this.model.toggle();
            }
        });

        // The main view of the application
        var App = Backbone.View.extend({

            // Base the view on an existing element
            el: $('#main'),

            initialize: function(){

                // Cache these selectors
                this.total = $('#total span');
                this.list = $('#services');

                // Listen for the change event on the collection.
                // This is equivalent to listening on every one of the 
                // service objects in the collection.
                this.listenTo(services, 'change', this.render);


                // Create views for every one of the services in the
                // collection and add them to the page

                services.each(function(service){

                    var view = new ServiceView({ model: service });
                    this.list.append(view.render().el);

                }, this);   // "this" is the context in the callback
            },

            render: function(){

                // Calculate the total order amount by agregating
                // the prices of only the checked elements

                var total = 0;
                console.log(services.getChecked());

                Handlebars.each(services.getChecked(), function(elem){
                    console.log(total);
                    total += elem.get('price');
                });

                // Update the total price
                this.total.text('$'+total);

                return this;

            }

        });

        new App();

    }
});

}); });

Below is a workable snippet of your code.以下是您的代码的可行片段。 You have defined a ServiceView , which is created for each service in your set, however within this view, you are working with the collection as a whole, not this.model and your handlebars template has a for loop in it.您已经定义了一个ServiceView ,它是为您的集合中的每个服务创建的,但是在此视图中,您正在处理整个集合,而不是this.model并且您的把手模板中有一个 for 循环。

This means that you end up displaying the collection as many times as there are models in the collection.这意味着您最终显示的集合与集合中的模型一样多。 The example below duplicates the list twice as there are 2 records in the list.下面的示例将列表复制两次,因为列表中有 2 条记录。

There are 2 possible solutions:有两种可能的解决方案:

  • Rename your ServiceView to ServicesView and remove the loop within App initialize.将您的ServiceView重命名为ServicesView并删除 App 初始化中的循环。

  • Remove the loop in your template and change the call to this.$el.html(tpl(this.model.toJSON()));删除模板中的循环并将调用更改为this.$el.html(tpl(this.model.toJSON()));

 // Create a model for the services var Service = Backbone.Model.extend({ // Will contain three attributes. // These are their default values defaults:{ title: 'My service', price: 100, checked: false }, // Helper function for checking/unchecking a service toggle: function(){ this.set('checked', !this.get('checked')); } }); // Create a collection of services var ServiceList = Backbone.Collection.extend({ // Will hold objects of the Service model model: Service, // Return an array only with the checked services getChecked: function(){ return this.where({checked:true}); } }); //Retrieve the list of services $.ajax({ type: "GET", url: "http://www.mocky.io/v2/588b429d300000d11afa8d97", async: true, success: function(response){ // Prefill the collection with a number of services. var services = new ServiceList(response); var ServiceView = Backbone.View.extend({ tagName: 'li', events:{ 'click': 'toggleService' }, initialize: function(){ // Set up event listeners. The change backbone event // is raised when a property changes (like the checked field) this.listenTo(services, 'change', this.render); }, render: function(){ var tpl = Handlebars.compile($("#services-template").html()); //console.log(this.$el.selector); this.$el.html(tpl({services: services.toJSON()})); //console.log(this.$el); $('#serviceTable').append(this.$el); //document.getElementById('serviceTable').innerHTML = serviceData; // Create the HTML /* this.$el.html('<input type="checkbox" value="1" name="' + this.model.get('title') + '" /> ' + this.model.get('title') + '<span>$' + this.model.get('price') + '</span>'); this.$('input').prop('checked', this.model.get('checked')); */ // Returning the object is a good practice // that makes chaining possible return this; }, toggleService: function(){ this.model.toggle(); } }); // The main view of the application var App = Backbone.View.extend({ // Base the view on an existing element el: $('#main'), initialize: function(){ // Cache these selectors this.total = $('#total span'); this.list = $('#services'); // Listen for the change event on the collection. // This is equivalent to listening on every one of the // service objects in the collection. this.listenTo(services, 'change', this.render); // Create views for every one of the services in the // collection and add them to the page services.each(function(service){ var view = new ServiceView({ model: service }); this.list.append(view.render().el); }, this); // "this" is the context in the callback }, render: function(){ // Calculate the total order amount by agregating // the prices of only the checked elements var total = 0; console.log(services.getChecked()); Handlebars.each(services.getChecked(), function(elem){ console.log(total); total += elem.get('price'); }); // Update the total price this.total.text('$'+total); return this; } }); new App(); } });
 <form id="main" method="post" action="submit.php"> <h1>My Services</h1> <div id="serviceTable"></div> <ul id="services"> <script id="services-template" type="text/x-handlebars-template"> <!-- The services will be inserted here via handlebars--> {{#each services}} <li> <input type="checkbox" value="1" name="{{title}}"/> {{title}} <span>${{price}} </span> </li> {{/each}} </script> </ul> <p id="total">total: <span>$0</span></p> <input type="submit" id="order" value="Order" /> </form> <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/backbone.js/1.3.3/backbone-min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/handlebars.js/4.0.6/handlebars.min.js"></script>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM