用Html/Javascript填充Textarea,同时保持它与knockout.js解耦

Populate Textarea with Html/Javascript while keeping it decoupled with knockout.js

本文关键字:knockout 解耦 js Html Javascript 填充 Textarea      更新时间:2023-09-26

我试图用动态代码填充一个文本区,随着客户端事件id的变化而变化。我下面的实现如下,我不确定是否有更好的方法。我遇到了两个问题。首先是我想删除绑定html后的数据绑定元素,并在文本区显示它,其次是javascript正在消失。想法吗?我试图做什么谷歌分析做当你复制和粘贴他们的代码,但我的页面上是动态的。

<script type="text/javascript">
    app.viewModel.members.widgets = {
        type: ko.observable(),
        code: ko.observable(),
        list: [
            { id: 'registration', type: '@((int)WidgetType.Registration)' },
            { id: 'payments', type: '@((int)WidgetType.Payments)' }
        ]
    };

    app.viewModel.members.widgets.selectedWidget = ko.computed(function() {
        if (!app.viewModel.members.widgets.type())
            return null;
        return ko.utils.arrayFirst(app.viewModel.members.widgets.list, function(widget) {
            return widget.type == app.viewModel.members.widgets.type();
        });
    });

    ko.bindingHandlers.initializeValueWithHtml = {
        update: function(element, valueAccessor) {
            var value = valueAccessor();
            if (ko.isObservable(value)) {
                value($(element).html());
            }
        }
    };
</script>
输入

<textarea data-bind="value: code, click: function(vm, e)  { $(e.currentTarget).select(); } ">
            </textarea>
模板

   <pre class="hidden" data-bind="if: $root.members.widgets.selectedWidget(), initializeValueWithHtml: code">
            <div data-bind="attr: { id: 'ebt-' + $root.members.widgets.selectedWidget().id,  'data-href': 'https://test.com/widgets/v1/' +  $root.members.widgets.selectedWidget().id + '?eventid=@Model.EventId    ' }" data-width="100%" data-height="500px"></div>
            <script type="text/javascript">
                (function (d, s, id) {
                    var js, fjs = d.getElementsByTagName(s)[0];
                    if (!d.getElementById(id)) {
                        js = d.createElement(s);
                        js.id = id;
                        js.async = true;
                        js.src = "//test.com/scripts/exposure.widgets.min.js";
                        fjs.parentNode.insertBefore(js, fjs);
                    }
                })(document, "script", "ebt.widgets");
            </script>
        </pre>

将代码模板放在pre中可能会做一些奇怪的事情,并使其对您来说更加困难。相反,我建议在代码模板中使用字符串,如下所示:

var codeTemplate = 
'<div id="ebt-{0}" data-href="https://test.com/widgets/v1/{1}?eventid=@Model.EventId" data-width="100%" data-height="500px"></div>'n' +
'<script type="text/javascript">'n' +
'    (function (d, s, id) {'n' +
'        var js, fjs = d.getElementsByTagName(s)[0];'n' +
'        if (!d.getElementById(id)) {'n' +
'          js = d.createElement(s);'n' +
'          js.id = id;'n' +
'          js.async = true;'n' +
'          js.src = "//test.com/scripts/exposure.widgets.min.js";'n' +
'          fjs.parentNode.insertBefore(js, fjs);'n' +
'        }'n' +
'    })(document, "script", "ebt.widgets");'n' +
'<'/script>';

然后创建一个compute,它将根据你的observable填充模板中的参数:

app.viewModel.code = ko.computed(function() {
    var selected = app.viewModel.members.widgets.selectedWidget();
    if (selected) {
        var result = codeTemplate.replace('{0}',selected.id).replace('{1}',selected.id);
        return result;
    } else {
        return "";
    }
});

可以删除initializeValueWithHtml绑定。

这里是小提琴:http://jsfiddle.net/tlarson/Ycz5Q/

首先,我不太确定类型应该是什么,因为我不了解服务器端模型,所以我将它们设置为1和2。

要使用fiddle,请在第一个框中键入1,然后将其划掉。将第一个框中的值更改为2,然后将其选中。您应该看到,根据第一个框中的值,适当的代码加载到第二个框中。