【问题标题】:knockout hide all not active elements淘汰赛隐藏所有非活动元素
【发布时间】:2017-02-16 07:08:40
【问题描述】:

您好,我无法创建正确的函数来显示/隐藏元素。目标很简单,当您单击列表元素时,您将看到包含更多信息的 div(模板)。现在您必须再次单击同一列表元素以隐藏该元素。我想做的事: 例如,当我单击列表上的第一个元素并显示该元素的模板时,我转到列表上的第二个元素(或最后一个或任何其他元素)我单击它并想隐藏所有打开的元素(模板)但我只想查看我点击的元素的活动元素。现在我可以同时打开许多元素,我想将其更改为仅打开的活动元素并隐藏所有其余元素。这可以在淘汰赛中做到吗?或者也许我必须为此使用jquery? jsfiddle上的示例

HTML

<form action="#"> 
    <input placeholder="Search…" type="search" name="q" data-bind="value: query, valueUpdate: 'keyup'" autocomplete="off"> 
  </form>

  <div class="container">
    <div class="row">
      <div class="col-xs-12 col-sm-6 col-md-4 col-lg-4">
        <ul class="name-list" data-bind="foreach: filteredPeople">
          <li data-bind="attr:{class: $index == 0 ? 'active' : ''}, click: toggleshowMoreInfo" role="button">
            <span class="full-name" data-bind="text: fullName"></span>
          </li>

          <div class="hidden-sm hidden-md hidden-lg" data-bind="slideVisible: showMoreInfo, fadeDuration:600,template: {name: 'person-template'}"></div>
        </ul>

      </div>

      <div class="col-xs-12 col-sm-6 col-md-8 col-lg-8 hidden-xs" data-bind="foreach: filteredPeople">
        <div class="row" data-bind="slideVisible: showMoreInfo, fadeDuration:600,template: {name: 'person-template'}"></div>
      </div>
    </div>
  </div>


  <!-- template for presonal information -->
  <script type="text/html" id="person-template">
    <div class="col-xs-12 col-md-6">
      <p><span data-bind="text: fullName"></span></p>
    </div>
  </script>

JS

var data = [
  {
    "index": 0,
    "name": [{
      "first": "Barlow",
      "last": "Moore"
    }]
  },
  {
    "index": 1,
    "name": [{
      "first": "Valeria",
      "last": "Meadows"
    }]
  },
  {
    "index": 2,
    "name": [{
      "first": "Constance",
      "last": "Singleton"
    }]
  },
  {
    "index": 3,
    "name": [{
      "first": "Wilder",
      "last": "Steele"
    }]
  }
];

  var stringStartsWith = function (startsWith, string) {          
    string = string || "";
    if (startsWith.length > string.length)
        return false;
    return string.substring(0, startsWith.length) === startsWith;
  };

  ko.bindingHandlers.slideVisible = {
    update: function(element, valueAccessor, allBindings) {
      var value = valueAccessor();
      var valueUnwrapped = ko.unwrap(value);
      var duration = allBindings.get('fadeDuration') || 400;
      if (valueUnwrapped == true)
        setTimeout(function(){ $(element).fadeIn(duration); }, duration);
      else
        $(element).fadeOut(duration);
    }
  };

  /* show all data from json */
  function PersonInfo(data) {
    this.firstName = ko.observable(data.name[0].first);
    this.lastName = ko.observable(data.name[0].last);
    this.fullName = ko.computed(function() {
      return this.firstName() + " " + this.lastName();
    }, this);

    this.showMoreInfo = ko.observable(false);
    this.toggleshowMoreInfo = function () {
      this.showMoreInfo(!this.showMoreInfo())
    }
  }

  function PersonInfoViewModel() {
    var self = this;
    self.query = ko.observable('');
    self.mappedPersonalData = $.map(data, function(item) {  
      return new PersonInfo(item) 
    });
    self.filteredPeople = ko.computed(function () {
        return self.mappedPersonalData.filter(function (value) {
            if(self.query() === '' || self.query() === null){
               return true; //no query
            }
            if (stringStartsWith(self.query().toLowerCase(), value.firstName().toLowerCase()) || stringStartsWith(self.query().toLowerCase(), value.lastName().toLowerCase())){
               return true;
            }
            return false;
        });
    }); 
  }

  var viewModel = new PersonInfoViewModel();

  $(document).ready(function() {
    ko.applyBindings(viewModel);
  });

【问题讨论】:

    标签: jquery knockout.js


    【解决方案1】:

    这当然是可能的淘汰赛。您需要做的就是将您的切换功能向上移动到 PersonInfoViewModel,并在该循环中通过其他 personInfo 模型来关闭它们。

    self.toggleshowMoreInfo = function (person) {
        var people = self.filteredPeople();
        for(var i=0; i<people.length; i++){
            if(people[i] !== person && people[i].showMoreInfo()){
                people[i].showMoreInfo(false);
            }
        }
        person.showMoreInfo(!person.showMoreInfo());      
    }
    

    然后将您的点击绑定更改为$parent.toggleshowMoreInfo

    修改jsFiddle

    【讨论】:

      【解决方案2】:

      您可以通过让您的点击处理程序设置一个selectedPerson 属性来大大简化此操作,并向您的模板div 添加一个绑定以将当前person 对象与selectedPerson 对象进行比较。这样,您根本不必进行任何循环。 Knockout 将为您完成这一切。例如

      <ul data-bind="foreach: filteredPeople">
          <li data-bind="click: toggleSelectedPerson">
              <span class="full-name" data-bind="text: fullName"></span>
          </li>
          <div data-bind="slideVisible: $parent.selectedPerson() === $data, fadeDuration:600,template: {name: 'person-template'}"></div>
      </ul>
      
      <div data-bind="foreach: filteredPeople">
          <div data-bind="slideVisible: $parent.selectedPerson() === $data, fadeDuration:600,template: {name: 'person-template'}"></div>
      </div>
      
      // your model config
      this.selectedPerson = ko.observable(null);
      this.toggleSelectedPerson = function (person) {
        this.selectedPerson(this.selectedPerson() === person ? null : person);
      }
      // your model config continued...
      

      从另一个答案中获取并更新了 JSFiddle:https://jsfiddle.net/9swam66o/3/

      【讨论】:

        猜你喜欢
        • 2015-08-22
        • 2017-09-25
        • 1970-01-01
        • 2023-03-09
        • 2017-01-25
        • 2014-05-28
        • 1970-01-01
        • 2016-05-14
        • 1970-01-01
        相关资源
        最近更新 更多