2017-02-15 6 views
0

Привет, У меня есть проблема с созданием правильной функции для отображения/скрытия элементов. Цель проста, когда вы нажимаете элемент списка, вы увидите div (шаблон) с дополнительной информацией. Теперь вы должны щелкнуть снова в этом же элементе списка, чтобы скрыть этот элемент. Что я хочу сделать: пример, когда я нажимаю на первый элемент в списке, и шаблон для этого элемента будет показан, я перехожу ко второму элементу в список (или последний или любой другой), я нажимаю на него, и я хочу скрыть все открытые элементы (шаблоны), но я хочу видеть только активный элемент для элемента, который я нажал. Теперь я могу открыть много элементов в это же время, и я хочу изменить его для открытого только активного элемента и скрыть все остальное. Это можно сделать в knonckout? Или, может быть, я должен использовать 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); 
    }); 

ответ

1

Это, конечно, возможно нокаутом. Все, что вам нужно сделать, - переместить свою функцию переключения до PersonInfoViewModel и внутри этого цикла через другие модели personalInfo, чтобы закрыть их.

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

1

Вы могли бы упростить это значительно, делая ваш обработчик щелчка установить selectedPerson свойства, и добавить привязку к вашей диве шаблона для сравнения текущий person объект selectedPerson объект. Таким образом, вам не придется делать никаких циклов. Нокаут сделает все для вас. Например.

<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/

+0

спасибо Graham это очень полезно. – mcmac