【问题标题】:How to bind Knockout viewModel for only available keys?如何仅为可用键绑定 Knockout viewModel?
【发布时间】:2015-04-03 15:18:55
【问题描述】:

我正在使用 MVC 中的 .cshtml 动态创建淘汰赛 data-bind 属性。我只想绑定 viewModel 中可用的那些属性,这些属性又是我从 restful WCF 的结果动态创建的。

所以 viewModel 中可能有也可能没有一些可用的键 例如:<span data-bind="text: cli"></span> 已创建。

但是当我绑定 viewModel 时,我收到一条错误消息,提示“在 viewModel 中找不到'cli' 属性”。但是,我想仅当 viewModel 中存在该键时才绑定该属性。

 $(document).ready(function () {
            debugger;
            $.ajax({
                cache: false,
                type: "GET",
                async: false,
                dataType: "json",
                url: requestURL,
                success: function (data) {
                    debugger;
                    if (data.GetCircuitCheckStatusResponse.Status.HasErrors == false) {
                        networkData = data.GetCircuitCheckStatusResponse.Response.RunningStatus.networkData;
                        diagnosticData = data.GetCircuitCheckStatusResponse.Response.RunningStatus.diagnosticData;
                        diagnosticsInfo = {};
                        //To Create boxPanel Datas
                        for (var i = 0; i < networkData.length; i++) {
                            diagnosticsInfo[networkData[i].ItemTitle] = networkData[i].itemValue;
                        }
                        //To Bind the data using Knockout 
                    }
                },
                error: function (xhr) {
                    debugger;
                    alert(xhr.responseText);
                }
            });
            debugger;
            var viewModel = ko.mapping.fromJS(diagnosticsInfo);
            ko.applyBindings(viewModel);
            // Every time data is received from the server:
            //ko.mapping.fromJS(data, viewModel);

        });
@foreach (var nameValue in childContainer.NameValueImageItemsList)
                                {
                                    var cssClass = "nameValueItem floatLeft" + " " + nameValue.DataBindName;
                                    <div class="@cssClass" style="">@nameValue.DisplayName</div>
                                    <div class="@cssClass" style="width: 200px; margin-right: 10px;" ><span data-bind="text: CLI"></span></div>
                                    <div class="@cssClass" style="width: 200px; margin-right: 10px;">
                                        <a>
                                            @if (nameValue.IconImageURL != null && nameValue.IconImageURL != "")
                                            {
                                                <img src="@nameValue.IconImageURL" alt="i"/>   
                                            }
                                        </a>
                                    </div>
                                    <div class="clearBOTH"></div>
                                }

【问题讨论】:

  • 我想到的唯一可能的方法是你应该这样做&lt;!-- ko if:cli --&gt;//your html element &lt;!--/ko--&gt;
  • 你能澄清一下整个方法吗?

标签: javascript c# html asp.net-mvc-4 knockout.js


【解决方案1】:

这是一个非常简单的方法:

ko.applyBindings({
  description: 'some description'
  // ,title: 'my title'
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>

Description: <span data-bind="text: description"></span><br />
Title: <span data-bind="text: !!title ? title : ''"></span>

一个相关的选项可能是您在视图模型上创建一个safeTitle 计算属性:

var Vm = function() {
  var self = this;
  self.description = 'my description';
  //self.title = 'my title';
  self.safeTitle = ko.computed(function() {
    return !!self.title ? self.title : '';
  });
};

ko.applyBindings(new Vm());
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>

Description: <span data-bind="text: description"></span><br />
Title: <span data-bind="text: safeTitle"></span>

此外,您还可以使用函数来实现,因此您不必为每个属性创建一个可观察对象:

var Vm = function() {
  var self = this;
  self.description = 'my description';
  //self.title = 'my title';
  self.safeGet = function(prop) {
    return !!self[prop] ? self[prop] : '';
  };
};

ko.applyBindings(new Vm());
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>

Description: <span data-bind="text: description"></span><br />
Title: <span data-bind="text: safeGet('title')"></span>

请注意,如果这些属性是可观察的,则此代码会略有不同,如果可以,则更加不同(和复杂)。

另一个选项可能是查看this blog post 的第 3 点,关于包装现有绑定:您可以创建另一个“文本”绑定来防止这种情况。

附言。我会仔细重新考虑你的设计。属性是“可选”这一事实很可能与某些领域概念有关。

PPS。您也可以考虑使用 Null Object Pattern 服务器端,这个问题就完全消失了。

购买力平价。这是规避问题的最后一种方法,(合乎逻辑,但)令我惊讶的是:

ko.applyBindings({
  desc: 'some description'
  // ,title: 'my title'
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>

Description: <span data-bind="text: $data.desc"></span><br />
Title: <span data-bind="text: $data.title"></span>

【讨论】:

  • 我尝试按照您建议的方式进行操作,但仍然收到类似“Microsoft JScript 运行时错误:'cli' 未定义”的错误。我相信这种情况正在发生,因为即使在 knockoutViewModel 中也没有创建密钥,我们正在检查它是否不为空......将会有未定义的属性......不知道如何处理这个......我我是 Knockout 的新手。请建议!
  • 对不起,伙计,但你的评论对我来说绝对是零意义。尝试编辑和改进您的问题,使其重现您的实际场景,我们可以提供更具体的帮助。
  • 如果“cli”或任何其他属性不在视图模型中,只有一件事如何处理......比如
  • 该评论对我来说也毫无意义。你真的应该更新你的问题,改进它,添加任何细节(并特别注意正确的拼写、语法、解释、降价和整体可读性)。
【解决方案2】:

这对我来说是这样的:

 <span data-bind="text: $data['@nameValue.DataBindName'] "></span>

【讨论】:

    猜你喜欢
    • 2023-03-12
    • 2014-05-05
    • 2013-11-30
    • 2019-02-20
    • 1970-01-01
    • 2014-03-28
    • 1970-01-01
    • 1970-01-01
    • 2014-09-07
    相关资源
    最近更新 更多