Knockout JS:使用exapnd选项

时间:2016-11-17 10:03:18

标签: javascript jquery html css knockout.js

这是我的数据结构。

=MetaData=
School
College
Home

=SubDetails=
School
    ClassRooms
    Library 
    OfficeRoom
College
    AdminOffice
    Departments
    Lab
    PlacementHall
Home
    LivingRoom
    StudyRoom
    Hall
    DiningHall
    Portico

将使用下拉菜单选择元数据值。例如,如果school是从下拉菜单中选择的值,则显示区域应显示为:

+ school x

在我的案例中点击了那个+展开图标后,它应该列出数据中的详细信息。

- School x
    ClassRooms
    Library 
    OfficeRoom

例如,如果我不断选择多个项目,比如说学校,大学,家庭等等。

- School x
    ClassRooms
    Library 
    OfficeRoom
+ College x
- Home x
    LivingRoom
    StudyRoom
    Hall
    DiningHall
    Portico

我试过的代码:

HTML:

<div class="DataDisplay">
    <!-- ko foreach: selectedMetaDataList -->
    <span class="metaHeader">
            <span>
                <a href="#" data-bind="click: $parent.expandMetaData"><i class="fa fa-plus" style="padding-right: 3px;"></i></a>
                <span data-bind="text: $data"></span>
                <span class="combineImgText">
                    <img data-bind="click: $parent.remove" class="delfilter" src="@Url.Content("~/Content/images/icon_x_purple_on.png")" width="15" height="15" />
                </span>
            </span>
        </span><br />
    <!-- /ko -->
    <span class="subDetails" style="display: none">
        <!-- ko foreach: selectedSubDetailsList -->
        <span data-bind="text: $data" style="margin-left:25px"></span><span class="combineImgText">
            <img data-bind="click: $parent.remove" class="delfilter" src="@Url.Content("~/Content/images/icon_x_purple_on.png")" width="15" height="15" />
        </span><br />
        <!-- /ko -->
    </span>                             
</div>

JS:

if(//matching condition)
{
    selectedMetaDataList.push(selectedMetaData().toString()); //ko.observableArray([])
    selectedSubDetailsList.push(value[i]); //ko.observableArray([])
}

expandMetaData: function () {          
    expandData($(".subDetails").is(':visible') ? true : false);
    $(".subDetails").toggle();
},

问题是如果我选择多个,那么只有最后添加元素(如果可扩展)并且它包括先前所选项目的所有子细节。我的问题是如何绑定特定的选定元数​​据以显示其子细节内容。过去两天我一直在努力:(

任何建议都会有帮助!

1 个答案:

答案 0 :(得分:3)

在没有看到你的视图模型的情况下,我能给你的最佳建议是:

  • 您的观看模型不必复制您的数据结构。它们是您的数据和视图之间的一个层,因此您可以进行更改,从而有益于您想要渲染的方式。
  • 不要使用jQuery隐藏/显示内容,使用淘汰赛的默认数据绑定:visiblecss

说明这些要点:

  • 一个视图模型,其中包含对内部主要类别
  • 的详细信息的引用
  • 隐藏和显示的visible绑定
  • 视图模型中的expanded状态,可自动更新UI的多个部分

&#13;
&#13;
var metaData = [
  "School",
  "College",
  "Home"
];

var subDetails = {
  School: [
    "ClassRooms",
    "Library",
    "OfficeRoom"
  ],
  College: [
    "AdminOffice",
    "Departments",
    "Lab",
    "PlacementHall"
  ],
  Home: [
    "LivingRoom",
    "StudyRoom",
    "Hall",
    "DiningHall",
    "Portico"
  ]
};

// An important purpose of this view model is to include details _inside_ a meta item
var MetaViewModel = function(label) {
  // Expanded is used to bind to the visiblity of the details
  this.expanded = ko.observable(false);
  
  // Add a '+' or '-' sign based on expanded state
  this.label = ko.pureComputed(function() {
    return (this.expanded() ? "- " : "+ ") + label;
  }, this);
  
  // Here, we add the details to the item
  this.details = ko.observableArray(subDetails[label]);
  
  // Toggle flips the state of expanded
  this.toggle = function() {
    this.expanded(!this.expanded());
  }.bind(this);
  
  // Removes a detail from the item's details list
  this.remove = function(str) {
    this.details.remove(str);
  }.bind(this);
};

MetaViewModel.create = function(label) { return new MetaViewModel(label); };

var viewModel = {
   meta: metaData.map(MetaViewModel.create) // Creates a new viewmodel for each meta data category
}

ko.applyBindings(viewModel);
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<ul data-bind="foreach: meta">
  <li>
    <div data-bind="text: label, click: toggle"></div>
    <ul data-bind="foreach: details, visible: expanded">
      <li data-bind="text: $data + ' X', click: $parent.remove"></li>
    </ul>
</ul>
&#13;
&#13;
&#13;