سؤال

I don't think I'm doing this properly, and I haven't really been able to figure out why. I'm new to Knockout and SignalR and just kind of putzing through it.

Currently, if I put a debug HTML element on my page and databind it to dashboard on the ViewModel, I get all of my JSON outputted.

Although, if I try to do any databinding, I get undefined errors. Like for instance I tried to do the following:

<div data-bind="with: dashboard">
    <table class="table table-striped">
        <tr>
            <th>Staff</th>
            <th>Certification</th>
            <th>Code</th>
            <th>Type</th>
            <th>Organization</th>
            <th>Location</th>
            <th>Requirement</th>
            <th>Requirement Type</th>
            <th>Start</th>
            <th>Term</th>
            <th>End</th>
        </tr>
        <tr data-bind="foreach: expiringRequirements">
            <td data-bind="text: Name"></td>
            <td data-bind="text: Certification"></td>
        </tr>
    </table>
</div>

I get an undefined error for expiringRequirements but I also get an undefined for ExpiringRequirements (which is actually what is spit back in my JSON).

Can anyone help and tell me what I'm doing wrong? As far as I can tell, the SignalR part is working perfectly.

Also, would it make more sense to move the individual observables into the ViewModel? Ideally if only one section changes I would target it directly, I feel like it's unnecessary putting them into a model.

Models and ViewModels

var dashboardViewModel = function (data) {
    var self = this;

    self.hub = $.connection.dashboardHub;
    self.expiringRequirements = ko.observableArray([]);
    self.completedNotes = ko.observable();
    self.newUsers = ko.observableArray([]);
    self.reportables = ko.observableArray([]);

    self.init = function (portalId) {
        self.hub.server.fetchDataReportingItemsAsync(portalId);
    }

    self.updateEntireDashboard = function (result) {
        self.expiringRequirements(data.ExpiringRequirements);
        self.completedNotes(data.CompletedNotes);
        self.newUsers(data.NewUsers);
        self.reportables(data.Reportables);
    }
};

$(function () {
    var viewModel = new dashboardViewModel();
    var portalId = <%= PortalId %>

    ko.applyBindings(viewModel);

    $.connection.hub.logging = true;

    hub = $.connection.dashboardHub;
    $.connection.hub.start().done(function () {
        viewModel.init(portalId);
    });

    hub.client.upadateDashboardData = function (data) {
        viewModel.updateEntireDashboard(JSON.parse(data));
    }

    
});

Edit: Updated my viewmodel and removed the model since the pieces of the viewmodel will be separate anyway and can update independently. Makes more sense to flatten it out to me. However, binding it still not functional

Hub

public async void FetchDataReportingItemsAsync(int portalId)
{
    PortalId = portalId;
    var getNewUsersTask = GetNewUsersAsync();
    var getReportablesTask = GetReportablesAsync();
    var getExpiringReqsTask = GetExpiringRequirementsAsync();
    //var getCompletedNotesTask = GetCompletedNotesAsync();
    
    //Ensure that this includes every awaitable task
    await Task.WhenAll(getNewUsersTask, getReportablesTask, getExpiringReqsTask);

    DashboardReportingViewModel vm = new DashboardReportingViewModel()
    {
        NewUsers = getNewUsersTask.Result,
        Reportables = getReportablesTask.Result,
        ExpiringRequirements = getExpiringReqsTask.Result
        //CompletedNotes = getCompletedNotesTask.Result
    };
    
    Clients.All.updateDashboardData(vm);
}
هل كانت مفيدة؟

المحلول 2

I didn't realize that I changed the parameter in my Viewmodel's updateEntireDashboard to result and didn't update data.ExpiringRequirements etc to result.ExpiringRequirements

Works as expected now.

نصائح أخرى

If you do viewModel.dashboard(data); it won't work because it would just replace the observables with the non observable properties in data, and if you use viewModel.dashboard(new Dashboard(data)); it wont work either because it will actually create new observable that are different from the ones that the dom has been bound to. The best way I know to update a bunch of existing observables with new data is to use the knockout mapping plugin.

I think your with binding is wrong:

<div data-bind="with: dashboard">

This makes viewModel.dashboard the binding-context for all the rest of your data bindings.

Since viewModel.dashboard is undefined, it makes sense that you would get "undefined errors".

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top