1

我有一个knockout component呈现员工姓名的名称。在这个组件中,我可以通过callback函数来​​更改显示的员工姓名的格式。

但是我遇到了无法更改组件代码的情况。但我必须添加编辑按钮以显示模式弹出窗口以更新用户信息,如下图所示:

在此处输入图像描述

我如何设法使用callback组件提供的功能显示此编辑按钮。但是我遇到了绑定click event这个按钮的问题。

问题是:即使我定义了回调函数ShowModal,它也没有被调用。

这是我的代码:

组件注册:

ko.components.register('emp-box', {
      viewModel: function(params) {
      var self = this;
      self.Name = ko.observable();
      self.Callback = params.formatCallback;

      if(self.Callback !== undefined)
      {
        self.Name(self.Callback(params.EmpName));
      }
      else
      {
        self.Name(params.EmpName.firstName + ', ' + params.EmpName.lastName);
      }

    },
    template: '<div class="name-container"><span data-bind="html: Name"></span></div>'
});

视图模型

var vm = function() {
    var self = this;
    self.Emps = [{'Details': {firstName: 'First Name-A', lastName: 'Last Name-A'}},
                 {'Details': {firstName: 'First Name-B', lastName: 'Last Name-B'}}];

    // CALLBACK
    self.changeFormat = function(item)
    {
        return item.firstName + ' - ' + item.lastName + ' <span class="action" data-bind="click: ShowModal">Edit</span>';
    }

    self.ShowModal = function(item)
    {
        alert(1);
    }       
}

ko.applyBindings(new vm());

HTML:

<div data-bind='foreach: Emps'>
  <div data-bind='component: {
       name: "emp-box",
       params: {EmpName: Details, formatCallback: $root.changeFormat}
  }'></div>
</div>

工作小提琴: 小提琴

4

1 回答 1

1

如评论中所示,您正试图通过html绑定添加更多“敲除代码”来使视图动态化。这行不通。

html绑定甚至可以运行之前,敲除必须已经计算出绑定,因为它怎么会知道它需要运行html绑定?一旦绑定阶段完成,它就完成了。因此,您不能以这种方式注入更多的淘汰赛绑定。

Knockout 视图很灵活,只需添加您希望它们拥有的所有部分并动态显示它们。在这种情况下,您希望有一个按需显示的“编辑”按钮。if绑定很容易:

<div class="name-container">
    <span data-bind="text: displayName"></span>
    <span class="action" data-bind="if: canEdit, click: onEdit">Edit</span>
</div>

现在控制它的视图模型需要一个canEdit值和一个onEdit值,分别是布尔值和函数。这些可以params在组件绑定期间进行控制。

当您将 displayName 设为计算并将名称格式化函数存储在 observable 中时,您甚至可以动态切换名称格式。运行下面的代码示例以查看它的实际效果。

// emp-box.component.js ----------------------------------------------------
function standardNameFormat(emp) {
    return ko.unwrap(emp.lastName) + ', ' + ko.unwrap(emp.firstName);
}

ko.components.register('emp-box', {
    viewModel: function (params) {
        this.emp = params.emp;
        this.displayName = ko.computed(function () {
            var formatter = ko.unwrap(params.formatter) || standardNameFormat;
            return formatter(params.emp);
        });
        this.canEdit = params.canEdit;
        this.onEdit = params.onEdit;
    },
    template: '<div class="name-container">\
        <span data-bind="text: displayName"></span>\
        <span class="action" data-bind="if: canEdit, click: onEdit">Edit</span>\
    </div>'
});
// -------------------------------------------------------------------------

function EmployeeList(params) {
    var self = this;
    self.emps = ko.observableArray(params.emps);
    self.canEdit = ko.observable(false);

    self.firstnameLastname = function (emp) {
        return ko.unwrap(emp.firstName) + ' ' + ko.unwrap(emp.lastName);
    };
    
    self.nameFormat = ko.observable(self.firstnameLastname);
    self.showModal = function () {
        alert("You clicked on " + ko.unwrap(this.displayName));
    };
}
// -------------------------------------------------------------------------

ko.applyBindings(new EmployeeList({
    emps: [
        {firstName: 'First Name-A', lastName: 'Last Name-A'},
        {firstName: 'First Name-B', lastName: 'Last Name-B'}
    ]
}));
.name-container{
  padding: 5px;
  margin: 2px;
  background-color: #cacaca;
  border: 1px solid #888;
  border-radius: 5px;
}

.name-container span {
  margin: 5px;
}

body {
  font-family: arial,sans-serif;
  font-size: 13px;
}

.action {
  cursor: pointer;
  color: blue;
  text-decoration: underline;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>

<input type="checkbox" data-bind="checked: canEdit" id="chkEdit">
<label for="chkEdit">Enable editing</label>

<input type="radio" data-bind="value: null, checked: nameFormat" id="chkFmt1">
<label for="chkFmt1">Default format</label>
<input type="radio" data-bind="value: firstnameLastname, checked: nameFormat" id="chkFmt2">
<label for="chkFmt2">Alternative format</label>

<div data-bind='foreach: emps'>
  <div data-bind='component: {
       name: "emp-box",
       params: {emp: $data, formatter: $root.nameFormat, canEdit: $root.canEdit, onEdit: $root.showModal}
  }'></div>
</div>

于 2017-08-29T13:14:31.440 回答