如何在没有全局 viewModel 的情况下将点击处理程序绑定到 knockoutjs 中的模板?

发布于 2024-12-01 04:20:50 字数 1265 浏览 1 评论 0原文

我对 KnockoutJs 非常陌生,所以我希望有一个针对这种情况的众所周知的最佳实践,但我一直无法找到。

我有一个包含项目数组的视图模型。我想使用模板显示这些项目。我还希望每个项目都能够在查看和编辑模式之间切换。我认为最适合 Knockout 的是在主视图模型上或(可能更好)在数组中的每个项目上创建相关函数,然后在模板中绑定此函数。所以我在我的页面上创建了这段代码:

<ul data-bind="template: {name: testTemplate, foreach: items}"></ul>

<script id="testTemplate" type="text/x-jquery-tmpl">
  <li>
    <img src="icon.png" data-bind="click: displayEditView"  />
    <span data-bind="text: GBPAmount"></span>
    <input type="text" data-bind="value: GBPAmount" />
  </li>
</script>

<script>
(function() {
  var viewModel = new TestViewModel(myItems);
  ko.applyBindings(viewModel);
})();
</script>

在一个单独的文件中:

function TestViewModel(itemsJson) {

  this.items = ko.mapping.fromJS(itemsJson);

  for(i = 0; i < this.items.length; ++i) {
    this.items[i].displayEditView = function () {
      alert("payment function called");
    }
  }

  this.displayEditView = function () {
    alert("viewmodel function called");
  }
};

由于我的 JS 运行的环境,我无法向全局命名空间添加任何内容,因此需要匿名函数来创建和设置视图模型。 (如果有必要,我可以在一个命名空间中添加内容。)这个限制似乎破坏了我找到的所有示例,这些示例似乎依赖于全局 viewModel 变量。

PS如果有一种方法比我正在尝试的方法更适合knockoutJS,请随时提出建议!

I'm very new to KnockoutJs so I'm hoping that there is a well known best practice for this kind of situation that I just haven't been able to find.

I have a view model that contains an array of items. I want to display these items using a template. I also want each item to to be able to toggle between view and edit modes in place. I think what fits best with Knockout is to create the relevant function on either the main view model or (probably better) on each item in the array and then bind this function in the template. So I have created this code on my page:

<ul data-bind="template: {name: testTemplate, foreach: items}"></ul>

<script id="testTemplate" type="text/x-jquery-tmpl">
  <li>
    <img src="icon.png" data-bind="click: displayEditView"  />
    <span data-bind="text: GBPAmount"></span>
    <input type="text" data-bind="value: GBPAmount" />
  </li>
</script>

<script>
(function() {
  var viewModel = new TestViewModel(myItems);
  ko.applyBindings(viewModel);
})();
</script>

And this in a separate file:

function TestViewModel(itemsJson) {

  this.items = ko.mapping.fromJS(itemsJson);

  for(i = 0; i < this.items.length; ++i) {
    this.items[i].displayEditView = function () {
      alert("payment function called");
    }
  }

  this.displayEditView = function () {
    alert("viewmodel function called");
  }
};

Due to the environment my JS is running in I can't add anything to the global namespace, hence the annonymous function to create and set up the view model. (There is a namespace that I can add things to if it is necessary.) This restriction seems to break all the examples I've found, which seem to rely on a global viewModel variable.

P.S. If there's an approach that fits better with knockoutJS than what I am trying to do please feel free to suggest it!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

相权↑美人 2024-12-08 04:20:50

当您的 viewModel 无法全局访问时,有几个选项。

首先,您可以使用 templateOptions 参数将任何相关方法传递给模板绑定。

它看起来像(另请注意,静态模板名称应包含在引号中):

data-bind="template: {name: 'testTemplate', foreach: items, templateOptions: { vmMethod: methodFromMainViewModel } }"

然后,模板 vmMethod 内部将可用作 $item.vmMethod。如果您使用 templateOptions 作为最后一个参数,请确保大括号 { { 之间有一个空格,否则 jQuery 模板会尝试将其解析为自己的参数。

因此,您可以像这样绑定到它:

<img src="icon.png" data-bind="click: $item.vmMethod"  />

另一个选项是在每个项目上放置一个方法和对视图模型中任何相关内容的引用。看来您正在探索该选项。

最后,在 KO 1.3 中(希望在 9 月发布并很快推出测试版),将会有一个很好的方法来使用 jQuery 的实时/委托功能,并将其与您的 viewModel 连接起来(如本示例所示:http://jsfiddle.net/rniemeyer/5wAYY/

此外,“避免事件绑定中的匿名函数”这篇帖子的部分可能对您也有帮助。如果您正在寻找使用动态选择的模板进行就地编辑的示例,那么这篇文章 可能会有所帮助。

When your viewModel is not accessible globally, there are a couple of options.

First, you can pass any relevant methods using the templateOptions parameter to the template binding.

It would look like (also note that a static template name should be in quotes):

data-bind="template: {name: 'testTemplate', foreach: items, templateOptions: { vmMethod: methodFromMainViewModel } }"

Then, inside of the template vmMethod would be available as $item.vmMethod. If you are using templateOptions as the last parameter, then make sure that there is a space between your braces { { or jQuery templates tries to parse it as its own.

So, you can bind to it like:

<img src="icon.png" data-bind="click: $item.vmMethod"  />

The other option is to put a method and a reference to anything relevant from the view model on each item. It looks like you were exploring that option.

Finally, in KO 1.3 (hopefully out in September and in beta soon) there will be a nice way to use something like jQuery's live/delegate functionality and connect it with your viewModel (like in this sample: http://jsfiddle.net/rniemeyer/5wAYY/)

Also, the "Avoiding anonymous functions in event bindings" section of this post might be helpful to you as well. If you are looking for a sample of editing in place using a dynamically chosen template, then this post might help.

赴月观长安 2024-12-08 04:20:50

这是针对那些询问如何将变量方法(函数)传递给 Knockout 模板的人。模板的核心功能之一是使用变量数据,变量数据可以是Stringfunction。在 KO 中,这些变量可以嵌入到 dataforeach 属性中,以便模板进行渲染。嵌入在 dataforeach 中的对象,无论是 Stringfunction 等,都可以在此上下文中使用 <代码>$数据。

您可以查看这段代码,看看它是否可以帮助您将函数传递给 Knockout 模板。

function ViewModel() {
 this.employees = [
     { fullName: 'Franklin Obi', url: 'employee_Franklin_Obi', action: methodOne },
     { fullName: 'John Amadi', url: 'employee_John_Amadi', action: methodTwo }
 ],
this.methodOne = function(){ alert('I can see you'); },
this.methodTwo = function(){ alert('I can touch you'); }
}

ko.applyBindings(new ViewModel());


<ul  data-bind="template: { name: employeeTemplate, foreach: employees }" ></ul>
     <script type="text/html" id="employeeTemplate">
         <li><a data-bind="attr: { href: '#/'+url }, text: fullName, click: $data.action"></a></li>
    </script>

如果您想提供多个模板构造,您可以像这样向您的 ViewModel 引入 switch 方法,并使用 as 属性为每个项目(员工)引入别名。确保将开关键 linkable 添加到项目对象。

...
this.employees = [
     { fullName: 'Franklin Obi',  linkable : false },
     { fullName: 'John Amadi', url: 'employee_John_Amadi', action: methodTwo, linkable : true }
 ],
this.methodLinkTemplate = function(employee){return employee.linkable ? "link" : "noLink"; } //this is a two way switch, many way switch is applicable.
...

然后模板表单的id将被命名;

<ul  data-bind="template: { name: employeeTemplate, foreach: employees, as: 'employee' }" ></ul>
  <script type="text/html" id="noLink">
     <li data-bind="text: fullName"></li>
  </script>
  <script type="text/html" id="link">
     <li><a data-bind="attr: { href: '#/'+url }, text: fullName, click: $data.action"></a></li>
  </script>

我还没有运行过这个代码,但我相信这个想法可以节省别人的时间。

This is for those asking how to pass variable methods (functions) to Knockout Template. One of the core features of Templating is the consuming of variable data, which can be String or function. In KO these variables can be embedded in data or foreach properties for the Template to render. Objects embedded in data or foreach, be it String, function etc, can be accessed at this context using $data.

You can look at this code and see if it can help you to pass functions to Knockout Template.

function ViewModel() {
 this.employees = [
     { fullName: 'Franklin Obi', url: 'employee_Franklin_Obi', action: methodOne },
     { fullName: 'John Amadi', url: 'employee_John_Amadi', action: methodTwo }
 ],
this.methodOne = function(){ alert('I can see you'); },
this.methodTwo = function(){ alert('I can touch you'); }
}

ko.applyBindings(new ViewModel());


<ul  data-bind="template: { name: employeeTemplate, foreach: employees }" ></ul>
     <script type="text/html" id="employeeTemplate">
         <li><a data-bind="attr: { href: '#/'+url }, text: fullName, click: $data.action"></a></li>
    </script>

If you want to serve multiple Template constructs you can introduce a switch method to your ViewModel like this, and use as property to introduce alias for each item (employee). Make sure you add the switch key, linkable, to the item object.

...
this.employees = [
     { fullName: 'Franklin Obi',  linkable : false },
     { fullName: 'John Amadi', url: 'employee_John_Amadi', action: methodTwo, linkable : true }
 ],
this.methodLinkTemplate = function(employee){return employee.linkable ? "link" : "noLink"; } //this is a two way switch, many way switch is applicable.
...

Then the id of the Template forms will be named thus;

<ul  data-bind="template: { name: employeeTemplate, foreach: employees, as: 'employee' }" ></ul>
  <script type="text/html" id="noLink">
     <li data-bind="text: fullName"></li>
  </script>
  <script type="text/html" id="link">
     <li><a data-bind="attr: { href: '#/'+url }, text: fullName, click: $data.action"></a></li>
  </script>

I have not ran this codes but I believe the idea can save someones time.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文