2017-01-27 10 views
-1

У меня есть простая одностраничная программа, которая предназначена для моего обучения. На странице есть UL всех служб, которые я предоставляю. Этот список принадлежит JSON. Рядом с каждой услугой есть цена за нее и флажок, который пользователь может выбрать, если ему нужна услуга.Как интегрировать рули с магистралью

Под этим списком существует общая стоимость для всех выбранных услуг. Исходя из этого, не могли бы вы рассказать мне, что я делаю неправильно? Я пытаюсь интегрировать список сервисов в качестве шаблона руля. Вот 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> 

Вот это 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(); 

    } 
}); 

});

+0

А что не так? –

+0

Список повторяется 4 раза. Сумма не добавляется. –

ответ

0

Ниже приведенный фрагмент кода. Вы определили ServiceView, который создается для каждой службы в вашем наборе, однако в этом представлении вы работаете с коллекцией в целом, а не с this.model, а в вашем шаблоне handlebars есть цикл for.

Это означает, что вы в конечном итоге показываете коллекцию столько раз, сколько моделей в коллекции. В приведенном ниже примере дублируется список дважды, так как в списке есть 2 записи.

Есть 2 возможных решения:

  • переименовывать ServiceView в ServicesView и удалить петлю в App инициализации.

  • Снимите петлю в шаблоне и изменить вызов 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>