(knockout) заставить атрибут выбора поля со списком изменить список опций Bonded combobox

Я закодировал пример шаблона нокаута, который позволяет сделать выбор из поля со списком (первый список), что приведет к изменению списка параметров ограниченного поля со списком (второй список). Изменение, которое должно иметь место, заключается в том, что вновь загруженный список параметров должен содержать только параметры, которые имеют то же значение атрибута «fieldtype», что и выбранный в первом поле со списком (первый список).

Когда страница загружается впервые, первая загрузка второго поля со списком (второй список) выглядит хорошо, но затем, когда изменяется выбор первого поля со списком, второй список параметров не меняется должным образом.

вот скрипт с моим кодом: мой код в скрипте

Может ли кто-нибудь дать мне руководство, как сделать эту работу?

    <link rel="stylesheet" href="css/queryBuilder/Bootstrap/css/bootstrap.min.css" />
<link rel="stylesheet" href="css/queryBuilder/styles.css" />
<script src="../libs/knockout.js"></script>


<!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~MODEL~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
<div class="container">
  <div data-bind="with: group">
    <div data-bind="template: templateName"></div>
  </div>
</div>

<!-- ~~~~~~~~~~~~~~~group-template~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
<script type="text/html" id="group-template">
<br>
The intent of this page is that when <b>List One</b> selection changes <b>List Two</b> options reload with just the options from the get_jsonAttrList() call that have the same "fieldtype" as <b>List One</b>'s selection.
<br>
<br>
  <div class="alert alert-warning alert-group" style="border-width: 5px;border-color:blue;">
    List One: 
    <select data-bind="options: attributesAvailable, 
                     optionsText: 'display', 'fieldtype', 
                     selectedOptions: compareAttrObject, 
                     value: compareAttrObject
                    ">
    </select>
    <br>
    List Two:  
    <select data-bind="options: attributesAvailable2(), 
                     optionsText: 'display', 'fieldtype', 
                     selectedOptions: compareToAttrObject, 
                     value: compareToAttrObject
                    ">        
    </select>
  </div>
</script>


<script>
  window.addEventListener('load', function() {
    ko.applyBindings(new QueryBuilder.ViewModel());
  }, true);

function get_jsonAttrList() {
      return [{
          "dbcolumn" : "fid",
          "display" : "id #",
          "fieldtype" : "Number"
        }, {
          "dbcolumn": "fname",
          "display": "first name",
          "fieldtype": "Text"
        }, {
          "dbcolumn": "Apply_d",
          "display": "Application date",
          "fieldtype": "Date"
        }, {
          "dbcolumn": "location",
          "display": "location",
          "fieldtype": "Text"
        }, {
          "dbcolumn": "press_in",
          "display": "press in",
          "fieldtype": "Text"
        }, {
          "dbcolumn": "node1",
          "display": "node count",
          "fieldtype": "Number"
        }, {
          "dbcolumn": "comments",
          "display": "comments",
          "fieldtype": "Text"
        }, {
          "dbcolumn": "reg1_posname",
          "display": "Position Name",
          "fieldtype": "Text"
        }, {
          "dbcolumn": "reg1_inst_",
          "display": "inst count",
          "fieldtype": "Number"
        }, {
          "dbcolumn": "create_d8",
          "display": "create #",
          "fieldtype": "Number"
        }, {
          "dbcolumn": "mapped_d8",
          "display": "mapped #",
          "fieldtype": "Number"
        }, {
          "dbcolumn": "term_d",
          "display": "terminated date",
          "fieldtype": "Date"
        }, {
          "dbcolumn": "start",
          "display": "emp start date",
          "fieldtype": "Date"
        }]
    }


    //~~~~~~~~~~~~~~~~~~~~~~group~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    window.QueryBuilder = (function(exports, ko) {
      var Condition = exports.Condition;
      /**
       * creates an instants of the group template.
       */
      function Group() {
        var self = this;
        self.templateName = 'group-template';


        self.compareAttrObject = ko.observable("");
        self.attributesAvailable = ko.observable(get_jsonAttrList());
        self.compareToAttrObject = ko.observable("");
        self.attributesAvailable2 = ko.observable(new Array());

        self.compareAttrObject.subscribe(function() {
          var tempAttrList = get_jsonAttrList();
          if (tempAttrList != null && tempAttrList.length > 0) {
            if (self.compareAttrObject() != undefined && self.compareAttrObject()[0] != null) {
              alert("Length of list two BEFORE list one changed to ["+
                        self.compareAttrObject()[0].fieldtype+
                        "]..." + self.attributesAvailable2().length);

    //fail after firt//                
        self.attributesAvailable2 = ko.observable(new Array());
    //fail after firt//self.attributesAvailable2(new Array());
    //fail all//self.attributesAvailable2.splice(0,self.attributesAvailable2.length);
    //fail after first//while(self.attributesAvailable2.length > 0) {self.attributesAvailable2.pop();}

              for (var i = 0; i < tempAttrList.length; i++) {
                if (tempAttrList[i].fieldtype == self.compareAttrObject()[0].fieldtype) {
                  self.attributesAvailable2().push(tempAttrList[i]);
                }
              }
              alert("Length of list two AFTER list one changed to ["+
                        self.compareAttrObject()[0].fieldtype+
                        "]..." + self.attributesAvailable2().length);
            }
          }
        });


      }
      exports.Group = Group;
      return exports;
    })(window.QueryBuilder || {}, window.ko);

    //~~~~~~~~~~view model~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    window.QueryBuilder = (function(exports, ko) {

      var Group = exports.Group;

      function ViewModel() {
        var self = this;
        self.group = ko.observable(new Group());
      }

      exports.ViewModel = ViewModel;
      return exports;

    })(window.QueryBuilder || {}, window.ko);

</script>

person bkhummingbird    schedule 12.04.2018    source источник


Ответы (1)


Ваш код кажется запутанным в том, имеете ли вы дело с объектами или с массивами. Выпадающий список начальной загрузки в вашей скрипке, по-видимому, не допускает множественный выбор, поэтому за раз должен быть только один выбранный элемент.

Вы можете удалить привязку "selectedOptions" из выбора в своем шаблоне и оставить объект(ы) compareAttrObject в качестве наблюдаемых. Затем вы можете избавиться от всех мест, где вы обращаетесь к объектам, с помощью индексатора, такого как compareAttrObject()[0].

Ваши списки опций должны быть массивами, поэтому они должны быть объявлены как ko.observableArray() вместо ko.observable().

Наконец, вам нужно убедиться, что вы обновляете свои наблюдаемые объекты, а не заменяете их и нарушаете привязки. Каждый раз, когда срабатывает ваша подписка, атрибутыAvailable2 заменяются новым наблюдаемым массивом. Это должно изменить существующий наблюдаемый массив, удалив существующие элементы и добавив вместо этого только отфильтрованные элементы.

function get_jsonAttrList() {
  return [{ "dbcolumn" : "fid", "display" : "id #", "fieldtype" : "Number" }, { "dbcolumn": "fname", "display": "first name", "fieldtype": "Text" }, { "dbcolumn": "Apply_d", "display": "Application date", "fieldtype": "Date" }, { "dbcolumn": "location", "display": "location", "fieldtype": "Text" }, { "dbcolumn": "press_in", "display": "press in", "fieldtype": "Text" }, { "dbcolumn": "node1", "display": "node count", "fieldtype": "Number" }, { "dbcolumn": "comments", "display": "comments", "fieldtype": "Text" }, { "dbcolumn": "reg1_posname", "display": "Position Name", "fieldtype": "Text" }, { "dbcolumn": "reg1_inst_", "display": "inst count", "fieldtype": "Number" }, { "dbcolumn": "create_d8", "display": "create #", "fieldtype": "Number" }, { "dbcolumn": "mapped_d8", "display": "mapped #", "fieldtype": "Number" }, { "dbcolumn": "term_d", "display": "terminated date", "fieldtype": "Date" }, { "dbcolumn": "start", "display": "emp start date", "fieldtype": "Date" }] 
}


//~~~~~~~~~~~~~~~~~~~~~~group~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
window.QueryBuilder = (function(exports, ko) {
  var Condition = exports.Condition;
  /**
   * creates an instants of the group template.
   */
  function Group() {
    var self = this;
    self.templateName = 'group-template';


    self.compareAttrObject = ko.observable();
    self.attributesAvailable = ko.observableArray(get_jsonAttrList());
    self.compareToAttrObject = ko.observable("");
    self.attributesAvailable2 = ko.observableArray(new Array());

    self.compareAttrObject.subscribe(function() {
      var tempAttrList = get_jsonAttrList();
      if (tempAttrList != null && tempAttrList.length > 0) {
        if (self.compareAttrObject() != undefined && self.compareAttrObject() != null) {
          alert("Length of list two BEFORE list one changed to ["+
          			self.compareAttrObject().fieldtype+
          			"]..." + self.attributesAvailable2().length);
          
    			self.attributesAvailable2.removeAll();
          for (var i = 0; i < tempAttrList.length; i++) {
            if (tempAttrList[i].fieldtype == self.compareAttrObject().fieldtype) {
              self.attributesAvailable2.push(tempAttrList[i]);
            }
          }
          alert("Length of list two AFTER list one changed to ["+
          			self.compareAttrObject().fieldtype+
          			"]..." + self.attributesAvailable2().length);
        }
      }
    });


  }
  exports.Group = Group;
  return exports;
})(window.QueryBuilder || {}, window.ko);

//~~~~~~~~~~view model~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
window.QueryBuilder = (function(exports, ko) {

  var Group = exports.Group;

  function ViewModel() {
    var self = this;
    self.group = ko.observable(new Group());
  }

  exports.ViewModel = ViewModel;
  return exports;

})(window.QueryBuilder || {}, window.ko);
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-debug.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/jquery-ui-bootstrap/0.5pre/assets/css/bootstrap.min.css" rel="stylesheet"/>

<!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~MODEL~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
<div class="container">
  <div data-bind="with: group">
    <div data-bind="template: templateName"></div>
  </div>
</div>

<!-- ~~~~~~~~~~~~~~~group-template~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
<script type="text/html" id="group-template">
<br>
The intent of this page is that when <b>List One</b> selection changes <b>List Two</b> options reload with just the options from the get_jsonAttrList() call that have the same "fieldtype" as <b>List One</b>'s selection.
<br>
<br>
  <div class="alert alert-warning alert-group" style="border-width: 5px;border-color:blue;">
    List One: 
    <select data-bind="options: attributesAvailable, 
                     optionsText: 'display', 'fieldtype', 
                     value: compareAttrObject
                    ">
    </select>
    <br>
    List Two:  
    <select data-bind="options: attributesAvailable2(), 
                     optionsText: 'display', 'fieldtype', 
                     value: compareToAttrObject
                    ">        
    </select>
  </div>
</script>


<script>
  window.addEventListener('load', function() {
    ko.applyBindings(new QueryBuilder.ViewModel());
  }, true);

</script>

person Jason Spake    schedule 12.04.2018
comment
Это отлично сработало. Спасибо за помощь и объяснение. - person bkhummingbird; 12.04.2018