How to bind mouseover using knockout in a column i

2019-08-20 04:11发布

问题:

I am trying to bind a column in a table for mouseover event, if the cursor is over the column cell (not the column header), it will make the extended details (StrTimeDesc) visible. But when I run it, it will only display the 1st column (Work Date column) then the rest is blank.

here is my view:

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

            <th>Work Date</th>
            <th>Schedule Description</th>


        </tr>
    </thead>

    <tbody data-bind="foreach: Timesheet_headers">
        <tr>
            <td data-bind="text: workDate"></td>

            <td>
                <div data-bind="event: { mouseover: @parent.enableDetails, mouseout: @parent.disableDetails }">
                    <span data-bind="text: StrSchedDesc"></span>
                </div>
                <div data-bind="visible: IsTog">
                    <span data-bind="text: StrTimeDesc"></span>
                </div>
            </td>       

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

here is my knockout:

var Action =
{

    Timesheet_headers: ko.observableArray([]),
    workDate: ko.observable(),
    Schedule_description: ko.observable(),
    StrSchedDesc: ko.observable(),
    StrTimeDesc: ko.observable(),
    IsTog: ko.observable(false),

    detailsEnabled: ko.observable(false),
    enableDetails: function() {
        this.IsTog(true);
    },
    disableDetails: function() {
        this.IsTog(false);
    }
}

apply bindings are already done. I just omitted those parts because SO doesn't allow a post with a lot of codes and less details. If i remove the mouseover binding, the table runs fine. That mouseover bindings came from knockoutjs site.

UPDATE: here is my class

public class Timesheet_header
{

    [Key]
    public System.long AUTO_ID { get; set; }
    public System.Int64 Employee_id { get; set; }
    public System.Int16 Schedule_id { get; set; }
    [Required]
    [DataType(DataType.Date)]
    [DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
    public DateTime Work_date { get; set; }

    public string StrSchedDesc { get; set; }
    public string StrTimeDesc { get; set; }
    public bool IsTog { get; set; }

    public Timesheet_header()
    {
        IsTog = false;
    }
}

here is my data access (this successfully retrieves all records from the db)

public static List<Timesheet_header> GetLogs(long Employee_id, DateTime DateFrom, DateTime DateTo)
{
    var items = new List<Timesheet_header>();
    var command = new SqlCommand();
    try
    {
        command.CommandText = "GetTimeSheetHeaders";
        command.CommandType = CommandType.StoredProcedure;

        command.Parameters.AddWithValue("@Employee_id", Employee_id).Direction = ParameterDirection.Input;
        command.Parameters.AddWithValue("@DateFrom", DateFrom).Direction = ParameterDirection.Input;
        command.Parameters.AddWithValue("@DateTo", DateTo).Direction = ParameterDirection.Input;

        DataTable dt = SqlHelper.GetData(command);

        if (dt.Rows.Count <= 0) return items;

        foreach (DataRow row in dt.Rows)
        {
            Timesheet_header item = new Timesheet_header();

            item.AUTO_ID = (row["AUTO_ID"]).GetLong();

            item.Employee_id = (row["Employee_id"]).GetLong();

            item.Work_date = (row["Work_date"]).GetDbDate();                   

            item.StrSchedDesc = row["Schedule_description"].GetString();

            item.StrTimeDesc = " From " + row["Time_from"].GetString() + " - To " + row["Time_to"].GetString();

            items.Add(item);
        }
    }
    catch (Exception s)
    {
        return new List<Timesheet_header>();
    }

    return items;
}

I also updated my view and knockout above

回答1:

enableDetails and disableDetails should be prefixed with $parent as they are inside a foreach. Otherwise knockout will look for those functions inside each Timesheet_headers object.

<tbody data-bind="foreach: Timesheet_headers">
    <tr>
        <td data-bind="text: workDate"></td>

        <td>
            <div data-bind="event: { mouseover: $parent.enableDetails, mouseout: $parent.disableDetails }">
                <span data-bind="text: StrSchedDesc"></span>
            </div>
            <div data-bind="visible: detailsEnabled">
                <span data-bind="text: StrTimeDesc"></span>
            </div>
        </td>       

    </tr>
</tbody>

This still won't give you the expected result. workDate, Schedule_description, StrSchedDesc StrTimeDesc and IsTog should be properties of items in Timesheet_headers array. You don't need to have that in Action object.

There is also a typo here. O should be a lowercase in observable. Instead of

workDate: ko.Observable()

you should call

workDate: ko.observable()

Also, refer this answer and this fiddle. The question is same as yours.



回答2:

You can solve this with pretty simple CSS and keep JavaScript out of this style issue.

Add a class to the table, e.g. .show-details-on-hover. Next, add this CSS ruleset:

.show-details-on-hover tbody td:not(:first-child) {
    display: none;
}

.show-details-on-hover tbody tr:hover td:not(:first-child) {
    display: table-cell;
}