Knockout JS + Bootstrap + Icons + html绑定 [英] Knockout JS + Bootstrap + Icons + html binding

查看:133
本文介绍了Knockout JS + Bootstrap + Icons + html绑定的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

好吧,这个让我疯了......我似乎无法弄清楚在淘汰赛中制作html绑定的正确方法,与twitter bootstrap元素很好地配合。



我有以下HTML:

 < li>< a href =#> < i class =icon-user>< / i>启用/停用用户< / a>< / li> 

这一行实际上是其他一些li的一部分,但我只是在展示我需要简单的一点。



正如你所看到的,我也在这里使用twitter bootstrap,如图标类所示。



好的,所以这一切都很好,当我渲染我的菜单标签正确显示时,所有都很好地以引导样式呈现,一切都很棒。



现在,我想改变这一点,所以不是菜单选项总是说同样的东西,它会根据视图模型而改变。



For我的视图模型我正在使用具有如下视图模型的knockout.js:

  function UserListViewModel()
{
var self = this;
self.ListItems = ko.observableArray([]);

self.LoadListData = function()
{
self.ListItems([]);
$ .getJSON('/ api / getusers',null,function(results)
{
self.ListItems(results);
}
}
}

使用'LoadListData'函数加载时的可观察数组工作正常,并加载ListItems使用我在Json中的API返回的记录数组,每条记录如下所示:



{recordid:1,loginname:joe, fullname:joe person,isallowedlogin:1}



这只是一条记录,有多条记录,都是从我的db中的users表中检索的



此问题所关注的属性是isallowedlogin属性。



我目前正在绑定此列表使用敲出模板绑定的用户到我的文档中的表:

 < tbody data-bind =template:{ name:'UserListItemTemplate',foreach:ListItems,as:'ListItem'}> 
< / tbody>

我在这个问题的开头展示的LI标签是该模板的一部分......

 < script type =text / htmlid =UserListItemTemplate> 
< tr data-bind =css:{success:loginallowed == 1,error:loginallowed == 0}>
< td data-bind =text:recordid> xx< / td>
< td>
< li>< a href =#>< i class =icon-user>< / i>启用/停用用户< / a>< / li>
< / td>
< / tr>
< / script>

同样,还有其他LI标签,锚点等,我只展示了这需要的东西问题。



到目前为止,这么好......



我得到一张桌子,所有用户都在它,以及每行末尾的链接,当我加载数据,并且所有绑定工作得很好时,行上的css会根据允许的登录状态变为绿色或红色。



正如我之前提到的,我现在想动态更改锚标记上的文本,以便



IF isallowedlogin = 1然后我得到

 < li>< a href =#>< i class =icon-user>< / I>停用用户< / a>< / li> 

呈现否则IF isallowedlogin = 0然后我得到

 < li>< a href =#>< i class =icon-user>< / i>启用用户< / a>< / li> 

呈现。所有prety简单的东西,或者我认为。



如果我使用文本绑定

  data-bind =text:'禁用用户'

或文本绑定在我的模型中使用computedObservable / observable ..

  data-bind =text:someComputedObservable()

事情有效,但是我放松了图标



如果我使用的话HTML绑定:

  data-bind =html:'< i class =...>< / i>在我的模型中禁用用户''

或带有computedObservable / observable的html绑定。

  data-bind =html:'< i class =...>< / i>' + someComputedObservable()

我得到淘汰赛抱怨解析错误和各种疯狂,即使我尝试使用像<这样的东西组装字符串和%22来编码特殊字符。



我的第三次尝试,只是使用一个计算的observable,并直接在函数中构建HTML字符串:

  function UserListViewModel()
{
var self = this;
self.ListItems = ko.observableArray([]);

self.GetListItemText = ko.computedObservable(function(ListItem)
{
if(ListItem.isloginallowed == 1){
return'< i class = icon-user>< / i>禁用用户';
}
其他{
返回'< i class =icon-user>< / i>启用用户';
}
});
}

然后我试图绑定:

  data-bind =html:$ parent.GetListItemText

只是发现你不能将任何东西传递给一个计算的observable,所以我不知道我在表格中呈现链接时当前在哪一行数据,因此我无法做出决定文本应该是什么。



所以,最后,我想...让我们在视图模型之外尝试一个常规函数...



我知道我可以将当​​前对象传递给它,并且没有问题......



错误......



如果我定义:

  function GetMenuEnabledDisabledOptionText(ListItem)
{
if(ListItem.isloginallowed == 1){
return'< i class =icon-user>< / i>禁用用户';
}
else {
return'< i class =icon-user>< / i>启用用户';
}
}

在我的视图模型之外,然后按如下方式绑定它:

 < li>< a href =#data-bind =html:GetMenuEnabledDisabledOptionText> xx< /一个>< /锂> 

当我渲染菜单时,插入锚标记的ACTUAL选项文本是函数定义在JS文件中输入!!!





我想要做的就是在不杀死图标的情况下更新文本,如果我必须手工构建包含HTML的字符串,那么不管怎么说,但是如果可能的话,我想要淘汰只计算并更新相关的位。



这是一件非常简单的事情需要做,但方式JavaScript让它成为A **中的痛苦......



任何想法?



UPDATE 1



我弄清楚为什么我得到整个函数定义而不是返回的文本,看来我是一个工具,我没有发现我没有在函数名后附加括号,所以

 < li>< a href =# data-bi nd =html:GetMenuEnabledDisabledOptionText> xx< / a>< / li> 

应该是

 < li>< a href =#data-bind =html:GetMenuEnabledDisabledOptionText()> xx< / a>< / li> 

slaps self ....



仍在寻找关于文本更新的想法......

解决方案

好几个令人沮丧的时间之后。 ....



事实证明,我所要做的就是在我的模板绑定中将$ data传递给我的计算observable ......



所以,如果我们有以下视图模型:

  function UserListViewModel()
{
var self = this;
self.ListItems = ko.observableArray([]);

self.GetListItemText = ko.computedObservable(function(ListItem)
{
if(ListItem.isloginallowed == 1){
return'< i class = icon-user>< / i>禁用用户';
}
其他{
返回'< i class =icon-user>< / i>启用用户';
}
});
}

以前导致我的问题,因为'ListItem'始终为null ....



但是,如果我将我的Binding定义为:

  data- bind =html:GetListItemText($ data)

当我尝试访问我的ListItem时,神奇地说,我在循环的每一行都有我的属性: - )



哦,好的教训要学习....


ok, this one is driving me nuts... I just can't seem to figure out the correct way to make html bindings in knockout, play nicely with twitter bootstrap elements.

I have, the following HTML:

<li><a href="#"><i class="icon-user"></i> Enable/Disable User</a></li>

This line is actually part of some other li's that are in a ul, but I'm showing ONLY the bit I need for simplicity.

As you can see, I'm also using twitter bootstrap here, as is evidenced by the icon class.

Ok, so that's all good, when I render my menu that a tag shows up correctly, all nicely rendered in bootstrap style, and everything is great.

Now, I want to change this, so that instead of the menu option always saying the same thing, it changes depending on the view model.

For my view models I'm using knockout.js with a view model that looks like the following:

function UserListViewModel()
{
  var self = this;
  self.ListItems = ko.observableArray([]);

  self.LoadListData = function()
  {
    self.ListItems([]);
    $.getJSON('/api/getusers',null,function(results)
    {
      self.ListItems(results);
    }
  }
} 

The observable array when loaded using the 'LoadListData' function, works perfectly, and loads the ListItems with an array of records returned from my API in Json, each record looks like the following:

{"recordid": 1, "loginname": "joe", "fullname": "joe person", "isallowedlogin": 1}

That's just one record, there are multiple, all retrieved from my users table in my db

the property that's of interest to this question is the "isallowedlogin" property.

I'm currently, binding this list of users to a table in my document, using the knockout template binding:

<tbody data-bind="template: { name: 'UserListItemTemplate', foreach: ListItems, as: 'ListItem' }">
</tbody>

And the LI tag I showed at the beginning of this question, is part of that template...

<script type="text/html" id="UserListItemTemplate">
  <tr data-bind="css: { success: loginallowed == 1, error: loginallowed == 0}">
    <td data-bind="text: recordid">xx</td>
    <td>
      <li><a href="#"><i class="icon-user"></i> Enable/Disable User</a></li>
    </td>
  </tr>
</script>

Again, there are other LI tags, and anchors etc, I'm showing only what's needed for this question.

So far, so good...

I get a table, with all my users in it, and a link at the end of each row, when I load the data, and all the bindings work great, the css on the row changes green or red depending on allowed to login status.

Now as I mentioned earlier, I now want to dynamically change the text on the anchor tag so that

IF isallowedlogin = 1 then I get

<li><a href="#"><i class="icon-user"></i> Disable User</a></li>

rendered otherwise IF isallowedlogin = 0 then I get

    <li><a href="#"><i class="icon-user"></i> Enable User</a></li>

rendered. all prety simple stuff, or so I thought.

if I use a text binding

data-bind="text: 'Disable User'"

or a text binding with a computedObservable / observable in my model..

data-bind="text: someComputedObservable()"

things work, BUT I loose the icon

if I use the HTML binding:

data-bind="html: '<i class="..."></i> Disable User'"

or a html binding with a computedObservable / observable in my model..

data-bind="html: '<i class="..."></i> ' + someComputedObservable()"

I get knockout complaining about parsing errors and all sorts of madness, even if I try to assemble the string using things like < and %22 to encode the special chars.

my third attempt, was to just use a computed observable, and build the HTML string directly in the function:

function UserListViewModel()
{
  var self = this;
  self.ListItems = ko.observableArray([]);

  self.GetListItemText = ko.computedObservable(function(ListItem)
  {
    if(ListItem.isloginallowed == 1) {
      return '<i class="icon-user"></i> Disable User';
    }
    else {
      return '<i class="icon-user"></i> Enable User';
    }
  });
} 

Then I tried to bind that:

data-bind="html: $parent.GetListItemText"

only to find out that you cant pass anything to a computed observable, so I had no idea which row of data I was currently on while rendering the link in the table, hence I can't make a decision on what the text should be.

So, finally, I thought... let's try a regular function, outside the view model...

I know I can pass the current object to that, and not have a problem...

wrong...

if I define:

function GetMenuEnabledDisabledOptionText(ListItem)
{
    if(ListItem.isloginallowed == 1) {
      return '<i class="icon-user"></i> Disable User';
    }
    else {
      return '<i class="icon-user"></i> Enable User';
    }
}

Outside my view model, then bind it as follows:

<li><a href="#" data-bind="html: GetMenuEnabledDisabledOptionText">xx</a></li>

When I render the menu, the ACTUAL option text that gets inserted into the anchor tag is the function definition as typed in the JS file!!!

All I want to be able to do is update the text without killing the icon, if I have to build the string including the HTML by hand, then so be it, but I'd like to get knockout to only compute and update the relevant bit if possible.

It's such a simple thing to need to do, but the way JavaScript is makes it a Pain in the A** to do...

Any Ideas?

UPDATE 1

I figured out the reason why I was getting the entire function definition rather than the returned text, it appears I was being a bit of a tool, I hadn't spotted that I wasn't appending the parenthesis after the function name, so

<li><a href="#" data-bind="html: GetMenuEnabledDisabledOptionText">xx</a></li>

should have been

<li><a href="#" data-bind="html: GetMenuEnabledDisabledOptionText()">xx</a></li>

slaps self ....

Still looking for ideas on the text updating though...

解决方案

Ok after several frustrating hours.....

it turns out, all I had to do was to pass $data to my computed observable in my template binding...

so, if we have the following view model:

function UserListViewModel()
{
  var self = this;
  self.ListItems = ko.observableArray([]);

  self.GetListItemText = ko.computedObservable(function(ListItem)
  {
    if(ListItem.isloginallowed == 1) {
      return '<i class="icon-user"></i> Disable User';
    }
    else {
      return '<i class="icon-user"></i> Enable User';
    }
  });
} 

Previously was causing me problems beacuse 'ListItem' as always null....

however, if I define my Binding as:

data-bind="html: GetListItemText($data)"

Magically when I then try to access my ListItem, I have my properties for each row I'm looping over :-)

Oh well, lessons to be learned....

这篇关于Knockout JS + Bootstrap + Icons + html绑定的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆