在KnockoutJS ViewModel上定义一个函数

时间:2017-03-29 07:29:20

标签: javascript knockout.js

在KnockoutJs中,我有一个我正在处理的管理页面的以下ViewModel:

function UsersViewModel() {
    var self = this;
    self.users = ko.observableArray([]);
    self.roles = ko.observableArray([]);

    $.post('http://localhost:23926/admin/acl/getroles',
        function(data) {
            const availableRoles = $.map(data,
                function(role) {
                    return new Role(role);
                });
            self.roles(availableRoles);
        },
        'json');

    $.post('http://localhost:23926/admin/acl/getuserroles',
        function(data) {
            const usersWithRoles = $.map(data,
                function(userWithRole) {
                    return new User(userWithRole);
                });
            self.users(usersWithRoles);
        },
        'json');

    self.selectedUser = ko.observable(self.users[0]);

    // operations
    self.setCurrentUser = function (user) {
        self.selectedUser(user);
    }

    self.SelectedUserHasRoles = ko.computed(function() {
        return self.selectedUser().roles().length > 0;
    });
}

在我的HTML中,我有以下内容:

<div class="col-md-6" data-bind="if: $root.SelectedUserHasRoles()">
  <h4><i class="fa fa-shield" aria-hidden="true"></i> Roles</h4>
  <hr />
  <div id="roles-wrapper" data-bind="foreach: $root.selectedUser().roles">
      <div class="role-token" data-bind="text: name"></div>
  </div>
</div>

我觉得应该有用!我想说:

  

如果所选用户有角色,则循环显示每个角色

如果这样有效,我会在左侧看到用户,在右侧看到所选用户的角色:

admin system

以上似乎不起作用,我不知道为什么!我收到错误:

error

第343行是这里的回归:

self.SelectedUserHasRoles = ko.computed(function() {
    return self.selectedUser().roles().length > 0;
});

我做错了什么?

1 个答案:

答案 0 :(得分:2)

您的问题来自于selectedUser为空,因为您使用空数组的第一个元素将其初始化:

self.users = ko.observableArray([]); 
// => self.users[0] === null, and maybe you should use self.users()[0]
self.selectedUser = ko.observable(self.users[0]); 

要避免此问题,您可以添加加载布尔值以指示您的应用程序未完成加载用户,或添加Promise.all调用,然后添加您的初始化逻辑。

使用承诺:

var promises = [$.post(...), $.post(...)]
Promise.all(promises).then(function(data) {
  // ... users and roles initalisation
  self.selectedUser(self.users()[0]);
})

// or via chained done method
$.post(...).done(function() {
  self.selectedUser(self.users()[0]);
})

或使用布尔逻辑(您可以优化此未经测试的代码):

self.loading = ko.observableArray(false)
self.isLoaded = ko.pureComputed(function() {
    return self.loading().all(function(x) { return x }) // ES5 syntax
})

self.selectedUser = ko.pureComputed(function() {
  if (self.isLoaded()) return users()[0]
  return null
})
$.post('..roles', function() {
  // ...
  self.loading()[0] = true
})
$.post('..users', function() {
  // ...
  self.loading()[1] = true
})

并在您的HTML中:

<div class="col-md-6" data-bind="if: $root.SelectedUserHasRoles()">
  <h4><i class="fa fa-shield" aria-hidden="true"></i> Roles</h4>
  <hr />
  <!-- ko if: !isLoaded() -->
  <span>Loading !</span>
  <!-- /ko -->
  <!-- ko if: isLoaded() -->
  <div id="roles-wrapper" data-bind="foreach: $root.selectedUser().roles">
      <div class="role-token" data-bind="text: name"></div>
  </div>
  <!-- /ko -->
</div>