简体   繁体   中英

Containerless if binding not working in KnockoutJS

I recently wanted to show a specific property if it is defined, and if it is not defined I want to show a DIV element with some instructions on it.

But i couldn't figure that out; I've tried with $root or even the bind property with it but without success.

Here is a sample of my code:

function InvestigatorInfo() {
  var self = this;
  self.Name = ko.observable();
  self.Description = ko.observable();
  self.TypeName = ko.observable();
  self.AssemblyName = ko.observable();
  self.ResultType = ko.observable();
  self.EnumTypeName = ko.observable();
  self.Obsolete = ko.observable();
  self.InvestigatorType = ko.observable();

  self.Properties = ko.observable();
  self.Requires = ko.observable();
}
InvestigatorInfo.prototype.fromJS = function(data) {
  var self = this;
  self.Name(data.Name || "");
  self.Description(data.Description || "");
  self.TypeName(data.TypeName || "");
  self.AssemblyName(data.AssemblyName || "");
  self.ResultType(data.ResultType || "");
  self.EnumTypeName(data.EnumTypeName || "");
  self.Obsolete(data.Obsolete || "");
  self.InvestigatorType(data.InvestigatorType || "");

  self.Properties(data.Properties.Properties || []);
  self.Requires(data.Requires.Interfaces || []);
}

And my index:

<ul class="collapsible" data-collapsible="accordion" data-bind="foreach:InvestigatorInfos">
  <li>
    <div class="collapsible-header">
      <i class="material-icons">view_quilt</i>
      <p class="blue-text" data-bind="text: TypeName"></p>
    </div>
    <div class="collapsible-body">

      <p class="style_p_row" ><b>AssemblyName:</b> <span data-bind="text: AssemblyName"></span></p>
                  <!-- ko if:Description -->
                  <p class="style_p_row" ><b>Description:</b> <span data-bind="text: Description"></span></p>
                  <!-- /ko -->
                  <!-- ko if:EnumTypeName -->
                  <p class="style_p_row" >
                  <b>EnumTypeName: </b><span data-bind="text: EnumTypeName"></span></p>
                  <!-- /ko -->
                  <p class="style_p_row" >
                  <b>InvestigatorType:</b> <span class="investigatortype-class" data-bind="text:investigatorName[InvestigatorType]"></span></p>
                  <p class="style_p_row" ><b>Name: </b><span data-bind="text: Name"></span></p>
                   <!-- ko if:Obsolete -->
                  <p class="style_p_row" ><b>Obsolete: </b><span data-bind="text: Obsolete"></span></p>
                   <!-- /ko -->
                  <p class="style_p_row" ><b>TypeName: </b><span data-bind="text: TypeName"></span></p>
                  <!-- ko if:ResultType -->
                  <p class="style_p_row" ><b>ResultType: </b><span data-bind="text: resultName[ResultType]"></span></p>
                  <!-- /ko -->

      <!-- ko ifnot:Properties-->
      <p class="blue-text padding_p">Properties</p>
      nothing is set
      <!-- /ko -->
      <!-- ko if: Properties-->
      <table class="bordered">
        <thead>
          <tr>
            <th data-field="Name">Name</th>
            <th data-field="Converter">Converter</th>
            <th data-field="ValidationName">ValidationName</th>
            <th data-field="EnumTypeName">EnumTypeName</th>
          </tr>
        </thead>
        <tbody data-bind="foreach: Properties">
          <tr>
            <td><span data-bind="text: Name"></span>
            </td>
          </tr>
        </tbody>
      </table>
      <!-- /ko -->
    </div>
    </li>
    </ul>

The Properties section within ko if: Properties always shows up, even if there are no values in the array behind it, rather than the elements defined within ko ifnot: Properties .

JSON data:

{
    "BrickInfos":  {
                       "BrickInfos":  [
                                          {
                                              "Properties":  {
                                                                 "Properties":  [

                                                                                ]
                                                             },
                                              "Implements":  {
                                                                 "Interfaces":  [
                                                                                    {
                                                                                        "TypeName":  "ITSR2.Bricks.Access.IAccessBareBoneBrick"
                                                                                    },
                                                                                    {
                                                                                        "TypeName":  "ITSR2.Bricks.Access.IAccessAppBrick"
                                                                                    }
                                                                                ]
                                                             },
                                              "Name":  "AccessBareBoneApp",
                                              "Description":  "",
                                              "TypeName":  "ITSR2.Bricks.Access.AccessBareBoneApp",
                                              "AssemblyName":  "ITSR2.Bricks.MSOffice, Version=3.0.0.0, Culture=neutral, PublicKeyToken=null",
                                              "Obsolete":  false
                                          },
                                          {
                                              "Properties":  {
                                                                 "Properties":  [
                                                                                    {
                                                                                        "Name":  "MainFile",
                                                                                        "Description":  "",
                                                                                        "ValidationType":  4,
                                                                                        "Converter":  8,
                                                                                        "EnumTypeName":  ""
                                                                                    }
                                                                                ]
                                                             },
                                              "Implements":  {
                                                                 "Interfaces":  [
                                                                                    {
                                                                                        "TypeName":  "ITSR2.Bricks.Access.IAccessBrick"
                                                                                    },
                                                                                    {
                                                                                        "TypeName":  "ITSR2.Bricks.Access.IAccessAppBrick"
                                                                                    }
                                                                                ]
                                                             },
                                              "Name":  "AccessFile",
                                              "Description":  "",
                                              "TypeName":  "ITSR2.Bricks.Access.AccessFile",
                                              "AssemblyName":  "ITSR2.Bricks.MSOffice, Version=3.0.0.0, Culture=neutral, PublicKeyToken=null",
                                              "Obsolete":  false
                                          },
                                     ]
                    }
}  

Your Properties property is an observable which looks like it holds an array, and is either set to data.Properties.Properties or an empty array ( [] ).

[] is a "truthy" value , so even if the code has assigned [] to Properties , the knockout if binding will see it as being populated. You need to check the length of it:

<!-- ko if:Properties().length == 0-->

Note the () - we need to call the observable to get the underlying array - the observable itself doesn't have a length property.

Regarding your update, taking Obsolete as another example, you're passing it false . This means that:

<!-- ko if: Obsolete -->

Is never going to show it's contents, as it's clearly false . You need to tailor it to the values you're expecting - since you're setting the default value to "" , you could check for that:

<!-- ko ifnot: Obsolete() === "" -->

So if it's specifically a blank string, it won't display, anything else will be displayed. Each of your properties will need to have a similar check depending on what you're passing to them and whether any "valid" values that you want to display could end up being treated as falsy values.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM