Получение примера нокаута для работы

StackOverflow https://stackoverflow.com/questions/5807118

  •  24-10-2019
  •  | 
  •  

Вопрос

После просмотра Nockout.js видео со Стивом Сандерсоном Я решил, что это будет здорово для сложных страниц пользовательского интерфейса.

Я работал живые примеры и прочитать документация. Анкет Я тогда нашел Отличная статья Райана Нимейера. Анкет Поэтому я хотел построить пример, похожий на Райана.

Это отобразит таблицу. Каждый ряд таблицы будет иметь бюджет.
Пользователь может ввести значения для каждого квартала.
Бюджет минус сумма кварталов даст оставшуюся сумму.
Если оставшаяся сумма не была нулю, к ней применил класс. Класс превратит цвет фона в красный.
Если бы какие -либо ряды остались, а не равен нулю, то кнопка сохранения будет отключена.

То, что я получил, было первоначальным отображением данных.

Что не работает:

  • Все ряды читаются хотя бы один с нулевым оставшимся.
  • Когда изменение квартала изменяется, оставшаяся стоимость не меняется.
  • Кнопка «Сохранить» никогда не включена.
  • JSON для сохранения неверно.

Код можно найти в эта скрипка а также ниже.

Во -первых, некоторые CSS, чтобы сделать все правильно:

   table.pretty {  
       margin: 1em 1em 1em 2em;  
       background: whitesmoke;  
       border-collapse: collapse;  
    }  
    table.pretty th, table.pretty td {  
       border: 1px silver solid;  
       padding: 0.2em;  
    }  
    table.pretty th {  
       background: gainsboro;  
       text-align: left;  
    }  
    table.pretty caption {  
       margin-left: inherit;  
       margin-right: inherit;  
    }  
    .RowError {  
       background-color: Red;  
       color: White;  
    }  

Затем представление:

<br /><br />  
<p>  
   There are <span data-bind="text: catagoryDetails().length">&nbsp;</span> rows in array<br />  
   I am flexible on changing the structure of data from server.<br />  
   I am flexible on how viewModel is built as long as it can be loaded from server <br />  
   I am flexible on how table is built.  
</p>  
<p>
   As Q1-Q4 values change the Remaining for row changes <br />  
   Row turns red if Remaining != 0 <br />  
   Unable to Save until all rows have a remaining of 0.<br>  
</p>  

<table id="pretty" > 
   <thead>
       <tr>
           <th>CatName</th>
           <th>Budget</th>
           <th>Q1Amt</th>
           <th>Q2Amt</th>
           <th>Q3Amt</th>
           <th>Q4Amt</th>
           <th>Remaining</th>
       </tr>
   </thead>
   <tbody data-bind="template: { name: 'catagoryDetailRowTemplate', foreach: catagoryDetails }"></tbody> 
</table>  

<script type="text/html" id="catagoryDetailRowTemplate"> 
   <tr data-bind="css: { RowError: Remaining !=  0 }">
       <td>
           <input type="hidden" data-bind="value: CatId"/>
           <span data-bind="text: CatName"> </span>
       </td>

       <td><span data-bind="text: BudgetAmt"> </span></td>
       <td><input data-bind="value: Q1Amt"/></td>
       <td><input data-bind="value: Q2Amt"/></td>
       <td><input data-bind="value: Q3Amt"/></td>
       <td><input data-bind="value: Q4Amt"/></td>
       <td><span data-bind="text: Remaining"> </span></td>
   </tr> 
</script>
<form action="ActionOnServer" >
   <input type="hidden" value="Not Set" id="ForServer" name="ForServer"/>
   <input type="submit" onclick="SendDataToServer()" value="Save" data-bind="enable: totalRemaining = 0" />
   <input type="button" onclick="alert('I would do cancel action')" value="Cancel" />
</form>

И JavaScript:

   function SendDataToServer() {
      // build data to send via json 
      var prepDataToSend = ko.toJS(viewModel.catagoryDetails);
      var mapDataForServer = ko.utils.arrayMap(prepDataToSend, function(item) {
         delete item.CatName;
         delete item.Remaining;    
         return item;
      });

      $("#ForServer").val(mapDataForServer);

      // if not debug return true and remove alert.
      alert(mapDataForServer);
      return false;
   }

   // data from the server
   // var dataFromServer = <%= new JavaScriptSerializer().Serialize(Model) %>; 

   // Hard code for now
   var dataFromServer = [
   { "CatId": 1000, "CatName": "Car wax", "Q1Amt": 50, "Q2Amt": 60, "Q3Amt": 90, "Q4Amt": 80, "BudgetAmt": 280 },
   { "CatId": 2000, "CatName": "Car Wippers", "Q1Amt": 20, "Q2Amt": 40, "Q3Amt": 60, "Q4Amt": 80, "BudgetAmt": 200 },
   { "CatId": 3333, "CatName": "Oil Change", "Q1Amt": 30, "Q2Amt": 70, "Q3Amt": 90, "Q4Amt": 10, "BudgetAmt": 200 },
   { "CatId": 4040, "CatName": "Gas", "Q1Amt": 0, "Q2Amt": 0, "Q3Amt": 0, "Q4Amt": 0, "BudgetAmt": 3000 }
   ];

   // constructor for each row of categories  ( adds obserbale )
   function oneCat(CatId, CatName, Q1Amt, Q2Amt, Q3Amt, Q4Amt, BudgetAmt) {
      this.CatId = CatId;
      this.CatName = CatName;
      this.Q1Amt = ko.observable(Q1Amt);
      this.Q2Amt = ko.observable(Q2Amt);
      this.Q3Amt = ko.observable(Q3Amt);
      this.Q4Amt = ko.observable(Q4Amt);
      this.BudgetAmt = ko.observable(BudgetAmt);
      this.Remaining = ko.dependentObservable(function () {
         var total = this.BudgetAmt();
         total = total - this.Q1Amt();
         total = total - this.Q2Amt();
         total = total - this.Q3Amt();
         total = total - this.Q4Amt();
         return total;
      }, this);
   }

   var mappedFromServer = ko.utils.arrayMap(dataFromServer, function (item) {
       return new oneCat(item.CatId, item.CatName, item.Q1Amt, item.Q2Amt, item.Q3Amt, item.Q4Amt, item.BudgetAmt);
   });

   // Here's my data model 
   var viewModel = {
       catagoryDetails: ko.observableArray([])
   };

   // add total of remaining
   viewModel.totalRemaining = ko.dependentObservable(function () {
      var total = 0;
      ko.utils.arrayForEach(this.catagoryDetails(), function (item) {
          var value = parseInt(item.Remaining, 10);
          if (!isNaN(value)) {
              total += value;
          }
      });
      return total;
   }, viewModel);

   viewModel.catagoryDetails(mappedFromServer);

   // turn on Knockout with the model viewModel    
   ko.applyBindings(viewModel);
Это было полезно?

Решение

Взгляните на это: http://jsfiddle.net/rniemeyer/qmxwe/

Основная проблема заключается в том, как вы получаете доступ к вашим наблюдаемым. Если вы передаете только наблюдаемый data-bind, тогда это разворачивает это для вас. Однако, если вы передаете выражение, вам необходимо получить доступ к наблюдаемой функции (например, в вашем фактическом JavaScript).

Итак, изменения, которые вы должны были бы внести:

data-bind="css: { RowError: Remaining() != 0 }"

data-bind="enable: totalRemaining() == 0"

И в вашем общем, зависимого от обеспечения, вам нужно получить доступ к оставшимся как:

var value = parseInt(item.Remaining(), 10);

Наконец, для вашей проблемы JSON, я думаю, что хороший способ справиться с этим - добавить метод Tojson к вашему oneCat тип. Там вы можете удалить свойства, которые вам не нужны. Это выглядело бы что -то вроде:

oneCat.prototype.toJSON = function() {
    var copy = ko.toJS(this);  //easy way to get a copy
    delete copy.CatName;
    delete copy.Remaining;
    return copy;
}

Затем вы можете просто использовать ko.tojson на своем объекте и при вызове json.stringify он будет использовать вашу функцию Tojson, когда видит oneCat.

Надеюсь это поможет.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top