数据绑定“attr”不起作用(?) [英] Data-bind "attr" doesn't work (?)

查看:150
本文介绍了数据绑定“attr”不起作用(?)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

目标



DOM 读取 data-product-id code>由KnockoutJS添加。



问题



我有以下标记:

 <! -  ko foreach:Summary.products  - > 
< li data-bind =attr:{'data-product-id':id}>
< div class =product-summary-actions float-right>
< button class =btn btn-danger btn-mini remove-item>
< i class =icon-remove>< / i>
< / button>
< / div>
< div class =product-summary-quantity>
< h6 data-bind =text:infoComposition>< / h6>
< / div>
< div class =product-summary-description>
< p data-bind =text:name>< / p>
< / div>
< / li>
<! - / ko - >

正如您所看到的,在使用<$注释之后的第一行有一个数据绑定c $ c> attr 绑定。看:

 < li data-bind =attr:{'data-product-id':id}> 

当我使用Chrome的控制台检查DOM时,我有以下几点:

 < li data-bind =attr:{'data-product-id':id}data-product-id =1> ...< /锂> 

正如您所见, data-product-id 已成功应用。但是,当我必须与他建立联系时,没有成功

在我的应用程序中有一个函数负责检查我的产品摘要中存在一个项目,并且以下循环执行此操作:

  $(element).each(function(){ 
var $ productId = $(this).closest(li)。data(product-id),
$ match = $(。summary)
.find( li [data-product-id =+ $ productId +])。length> 0;
console.log($ match);
});

总是返回 false 。换句话说,似乎jQuery不考虑由KnockoutJS生成的 data-product-id ,因为如果我手动添加数据产品ID 属性到我的项目(如下面的标记),所有工作正常。

 <! -  -  ko foreach:Summary.products  - > 
< li data-product-id =1>
< div class =product-summary-actions float-right>
< button class =btn btn-danger btn-mini remove-item>
< i class =icon-remove>< / i>
< / button>
< / div>
< div class =product-summary-quantity>
< h6 data-bind =text:infoComposition>< / h6>
< / div>
< div class =product-summary-description>
< p data-bind =text:name>< / p>
< / div>
< / li>
<! - / ko - >



好的...代码



我的 HTML:

 < button class =btn btn-success btn-small add
title =加入比较清单>
'icon-minus':'icon-plus'}>
< / i>
< / button>

我的JS:

 函数ProductLayoutViewModel(){
var self = this;

self.itemQuantity = ko.observable();
self.itemQuantityValid = ko.computed(function(){
var q = self.itemQuantity();
return q!=0&& q!=00 && q!= null&& q!=;
},this);

self.existsAtSummary = function(element){
$(element).each(function(){
$ productId = $(this).closest(li) .data(product-id);
$ match = $(。summary)
.find(li [data-product-id =+ $ productId +])。长度;

if(!$ match)
返回true;
else
返回false;
});
});
};

ViewModel = {
总结:新的SummaryViewModel(),
ProductLayout:new ProductLayoutViewModel()
};
$ b $ .ajax({
url:/ ProductsSummary / List?output = json,
dataType:json,
success:function(data) {
var mappingOptions = {
create:function(options){
return(new(function(){
this.finalMeasure = ko.computed(function(){
return this.quantity()> 1?
this.measure()+s:this.measure();
},this);

this .infoComposition = ko.computed(function(){
return this.quantity()+''+ this.finalMeasure();
},this);

ko。 mapping.fromJS(options.data,{},this);
})());
}
};

ViewModel.Summary.products = ko .mapping.fromJS(data,mappingOptions);
ko.applyBindings(ViewModel);
}
});

有人知道我该如何解决这个问题?谢谢!

解决方案

看起来您在那里有时间问题。



请注意,knockoutjs先通过您的js模型,然后用内容填充视图。因此,如果您正在测试或者在您的案例中对某个DOM结构进行迭代,那么您会直接遇到计时错误。



试着重新思考你在那里做什么。由于knockoutjs为html提供了数据,因此您的js代码中已经包含了所有数据。对我来说,这看起来像一个工作一轮。



例如:
您的模板:

 <! -  ko foreach:Summary.products  - > 
< li data-bind =attr:{'data-product-id':id}>
< / li>
<! - / ko - >

在knockoutjs中,您已经有产品清单和特定产品ID。所以你只需要检查你的列表的长度?或者我错过了那里的东西?



如果我弄错了,而你只是想触发另一个javascript,当你的列表呈现时,事件,当knockoutjs填充您的网页的内容。或者在dom准备好后触发你的javascript。

The Goal

Read the data-product-id from DOM added by KnockoutJS.

The problem

I have the following markup:

<!-- ko foreach: Summary.products -->
<li data-bind="attr: { 'data-product-id': id }">
    <div class="product-summary-actions float-right">
        <button class="btn btn-danger btn-mini remove-item">
            <i class="icon-remove"></i>
        </button>
    </div>
    <div class="product-summary-quantity">
        <h6 data-bind="text: infoComposition"></h6>
    </div>
    <div class="product-summary-description">
        <p data-bind="text: name"></p>
    </div>
</li>
<!-- /ko -->

As you can see, there is a data-bind at the first line after the comment with attr binding. Look:

<li data-bind="attr: { 'data-product-id': id }">

When I check my DOM using Chrome's console, I have the following:

<li data-bind="attr: { 'data-product-id': id }" data-product-id="1">...</li>

As you could see, data-product-id was successfully applied. But, when I have to make an interation with him, no success.

There is a function in my application that is responsible to check if an item exists on my Products Summary, and the following loop does this:

$(element).each(function () {
    var $productId = $(this).closest("li").data("product-id"),
    $match = $(".summary")
             .find("li[data-product-id=" + $productId + "]").length > 0;
     console.log($match);
});

Always the return is false. In other words, seems that jQuery doesn't consider the data-product-id generated by KnockoutJS because if I manually add the data-product-id attribute to my items (like the following markup), all works fine.

<!-- ko foreach: Summary.products -->
<li data-product-id="1">
    <div class="product-summary-actions float-right">
        <button class="btn btn-danger btn-mini remove-item">
            <i class="icon-remove"></i>
        </button>
    </div>
    <div class="product-summary-quantity">
        <h6 data-bind="text: infoComposition"></h6>
    </div>
    <div class="product-summary-description">
        <p data-bind="text: name"></p>
    </div>
</li>
<!-- /ko -->

Okay... Code

My necessary HTML:

<button class="btn btn-success btn-small add"
        title="Add to comparison list">
    <i data-bind="attr: { class: ProductLayout.existsAtSummary($element) ? 
                  'icon-minus' : 'icon-plus' }">
    </i>
</button>

My JS:

function ProductLayoutViewModel() {
    var self = this;

    self.itemQuantity = ko.observable("");
    self.itemQuantityValid = ko.computed(function () {
        var q = self.itemQuantity();
        return q != "0" && q != "00" && q != null && q != "";
    }, this);

    self.existsAtSummary = function (element) {
        $(element).each(function () {
            $productId = $(this).closest("li").data("product-id");
            $match = $(".summary")
                     .find("li[data-product-id=" + $productId + "]").length;

            if (!$match)
                return true;
            else
                return false;
        });
    });
};

ViewModel = {
    Summary: new SummaryViewModel(),
    ProductLayout: new ProductLayoutViewModel()
};

$.ajax({
    url: "/ProductsSummary/List?output=json",
    dataType: "json",
    success: function (data) {
        var mappingOptions = {
            create: function (options) {
                return (new (function () {
                    this.finalMeasure = ko.computed(function () {
                        return this.quantity() > 1 ? 
                               this.measure() + "s" : this.measure();
                    }, this);

                    this.infoComposition = ko.computed(function () {
                        return this.quantity() + ' ' + this.finalMeasure();
                    }, this);

                    ko.mapping.fromJS(options.data, {}, this);
                })());
            }
        };

        ViewModel.Summary.products = ko.mapping.fromJS(data, mappingOptions);
        ko.applyBindings(ViewModel);
    }
});

Someone knows how can I solve this problem? Thanks!

解决方案

looks like you have a timing problem there.

Please note, that knockoutjs first goes through your js models and then filles the view with content. So if you are testing or in your case iteration over some DOM structure, you run straight into a timing error.

Try to rethink what you are doing there. As knockoutjs is providing the html with data, you already have all data in your js code. To me this looks like a work-a-round.

eg: Your template:

<!-- ko foreach: Summary.products -->
<li data-bind="attr: { 'data-product-id': id }">
</li>
<!-- /ko -->

in knockoutjs you already have a list of products and the particular product-id. So all you need to do is to check the length of your list? Or do I miss something there?

If I get it wrong, and you just want to trigger another javascript which is doing something when your list is rendered, try to trigger some event when knockoutjs has filled your page with content. Or trigger your javascript after the dom is ready.

这篇关于数据绑定“attr”不起作用(?)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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