Hiding a part of column and making it appear throu

2019-08-23 01:49发布

问题:

I have a table:

table class="table">
    <thead>
        <tr>

            <th>ID</th>
            <th>Description</th>


        </tr>
    </thead>

    <tbody data-bind="foreach: Curriculums">
        <tr>
            <td data-bind="text: ID"></td>

            <td>
                <div data-bind="event: { mouseover: toggle, mouseout: toggle }>
                    <span data-bind="text: curCode"></span>
                </div>
                <div data-bind="visible: selected">
                    <span data-bind="text: curDescription"></span>
                </div>
            </td>       

        </tr>
    </tbody>
</table>

this is my knockout js

var Vm =
{

    Curriculums: ko.observableArray([]),
    ID: ko.Observable(),

    curCode: ko.observable(),
    curDescription: ko.observable(),

    selected: ko.observable(false),

    toggle: function() {
       this.selected(!this.selected());   
    }
}

I am trying to load all of the records of curriculum table. I successfully retrieved it and displayed it without the mouse over/out bindings. The problem is when I implement the mouseover and mouseout bindings, the knockout throws an error:

Uncaught Error: Unable to parse bindings.
Message: ReferenceError: toggle is not defined;
Bindings value: event: { mouseover: toggle}

how can I make this work? I am hiding the curDescription span if the mouse is not hovering and make it reappear when the mouse hovers to the curCode span

回答1:

toggle should be prefixed with $parent as you are using it inside a foreach binding. Otherwise knockout will look for the function inside each item in Curriculums array.

<tbody data-bind="foreach: Curriculums">
    <tr>
        <td data-bind="text: ID"></td>

        <td>
            <div data-bind="event: { mouseover: $parent.toggle, mouseout: $parent.toggle }>
                <span data-bind="text: curCode"></span>
            </div>
            <div data-bind="visible: selected">
                <span data-bind="text: curDescription"></span>
            </div>
        </td>       

    </tr>
</tbody>

This still won't give you the expected result. ID, curCode selected and curDescription should be properties of items in Curriculums array. You don't need to have that in your Vm

var Vm = {
  Curriculums: ko.observableArray([{
    ID: 1,
    curCode: "CS101",
    curDescription: "Why C#?",
    selected: ko.observable(false) // this needs to be an observable
  }, {
    ID: 2,
    curCode: "CS102",
    curDescription: "Javascript 101",
    selected: ko.observable(false)
  }]),

  // "item" will have the current "Curriculum" element which triggered the event
  toggle: function(item) {
    item.selected(!item.selected());
  }
}

Here's a fiddle for you test. Go through the knockout documentation and play around with some fiddles to get a good understanding of ko bindings.

As mentioned in this answer on the other question, you can achieve this by pure CSS. But again, it's important you understand how binding works inside foreach.



回答2:

Personally I'd just resort to CSS for such a simple thing, not least because it is more like a visual thing than program logic:

<table class="table show-on-hover">
    <thead>...</thead>
    <tbody data-bind="foreach: Curriculums">
    <tr>
        <td data-bind="text: ID"></td>
        <td>
            <span data-bind="text: curCode"></span>
            <span class="shown-on-hover" data-bind="text: curDescription"></span>
        </td>
    </tr>
</tbody

CSS:

table.show-on-hover tr .shown-on-hover {
    visibility: hidden;
}

table.show-on-hover tr:hover .shown-on-hover {
    visibility: visible;
}

However, this is an alternative way, not really an explaination of why your solution does not work. The other answer posted here does a nice job at explaining that.



标签: knockout.js