Javascript 在Durandal中绑定数据后动态绑定外部html文件

Javascript 在Durandal中绑定数据后动态绑定外部html文件,javascript,knockout.js,single-page-application,durandal,dynamic-binding,Javascript,Knockout.js,Single Page Application,Durandal,Dynamic Binding,我一直在搜索,我发现了一些与我类似的问题,但没有一个与我试图做的完全匹配(或者至少,解决方案对我不起作用)。我对Durandal真的很陌生,所以我不知道从哪里开始实现这一点。我正在开发一个测试应用程序,我有一个div,它绑定了数据以显示html,如下所示: 视图上的数据绑定 <div class="active-document-text" id="document-text" data-bind="html: documentBody"> mouseOver和mouseOut实际

我一直在搜索,我发现了一些与我类似的问题,但没有一个与我试图做的完全匹配(或者至少,解决方案对我不起作用)。我对Durandal真的很陌生,所以我不知道从哪里开始实现这一点。我正在开发一个测试应用程序,我有一个div,它绑定了数据以显示html,如下所示:

视图上的数据绑定

<div class="active-document-text" id="document-text" data-bind="html: documentBody">
mouseOver和mouseOut实际上只是在可选区域上移动鼠标时添加和删除CSS类。changeDocument()是我尝试使用以下dataservice对象加载html并处理CSS更改的过程

数据服务对象:

var getDocument = function (documentObservable, url) {
        documentObservable([]);

        if (!url) {
            console.log('Error: No url provided for document');
            documentObservable('<h1>Error: Document Not Found</h1>Document source was undefined.');
            return;
        }

        url = './app/views/' + url;

        var options = {
            url: url,
            type: 'GET',
            dataType: 'html',
            cache: false,
            error: queryFailed
        };

        return $.ajax(options)
            .then(querySucceeded);

        function querySucceeded(data) {
            console.log('Document \'' + url + '\' retrieval succeeded.');
            documentObservable(data);

            var currentID = 1;
            while (documentObservable().match(/\[selectable\]/g)) {
                documentObservable(documentObservable().replace('[selectable]', '<div class="selectable" selectID="' + currentID + '" data-bind="event: { mouseover: function () { $root.onmouseOver(' + currentID + '); }, mouseout: function () { $root.onmouseOut(' + currentID + '); }, click: function () { $root.mouseClick(' + currentID + '); } }">'));
                currentID++;
            }
        }

        function queryFailed(jqXHR, textStatus) {
            console.log('Error getting document ' + url + ': ' + textStatus);
            documentObservable('<h1>Error: Document Not Found</h1>' + textStatus);
        }

    };
var getDocument=function(documentObservable,url){
可观察的文件([]);
如果(!url){
log('错误:没有为文档提供url');
documentObservable('错误:未找到文档文档未定义文档源');
返回;
}
url='./app/views/'+url;
变量选项={
url:url,
键入:“GET”,
数据类型:“html”,
cache:false,
错误:查询失败
};
返回$.ajax(选项)
.然后(查询成功);
函数查询成功(数据){
log('Document\''+url+'\'检索成功');
可观察的文件(数据);
var-currentID=1;
while(documentObservable().match(/\[selective\]/g)){
documentObservable(documentObservable()。替换(“[可选]”,”);
currentID++;
}
}
函数查询失败(jqXHR,textStatus){
log('获取文档'+url+':'+textStatus'时出错);
documentObservable('错误:找不到文档'+文本状态);
}
};
数据服务是其中的关键。它加载html并用将用于数据绑定的长标记替换所有出现的[Selective]。 我还没有实现结束标记的替换,但这是一个简单的问题。div使用自定义属性selectID而不是ID的原因是,老板说使用ID是个坏主意,因为它们可以在文档中复制,而自定义属性不太可能出现

以及一份样本文件:

[selectable]
            &bull; This is a sample selectable area. This will be highlighted<br />
            when someone mouses over it.
            <br />[/selectable]
[可选]
&公牛;这是一个示例可选区域。这将突出显示
当有人在上面滑鼠时。
[/可选]
长div已经被[Selective]标记所取代,使具备基本HTML技能的人更容易构建示例文档


最终,目标是为创建文档的人提供一个易于使用的标记,而不必尝试粘贴长标记并跟踪其个人ID。我希望将鼠标事件绑定到viewmodel,因为它都是相同的活动(并且所有文档的分数将一起计算最终分数)。从用户的角度来看,当他们将鼠标悬停在可选择的文本上时,它应该只改变颜色(简单的jQuery)。如果他们单击它,它将检查他们是否选择了正确的类别(我已经有了这个工作)。我当前的问题是进行文本替换,并能够将事件绑定到视图的函数。

我不会使用knockoutjs html绑定

相反,使用Durandal compose绑定将新元素插入dom。Durandal也将为您处理绑定

见本文:

这对我来说非常有效。我最终在外部HTML中使用$root与事件数据绑定,效果非常好。谢谢你的帮助,Evan!似乎我在这方面还存在问题。在向老板介绍新解决方案后,他不喜欢长div标记,因为它需要包含事件绑定这是因为一个非开发人员可能会创建这些外部文档。我现在让它再次用AJAX调用抓取html文件,然后替换一个简单的自定义“[可选]“用长div标记并将其存储在可观察的视图中,但我仍然不确定如何将其与绑定合并到当前视图中。知道我可以从这里走到哪里吗?我被难住了。你能发布一些代码以及你希望它看起来像什么吗?我已经用附加信息更新了原始问题。
var vm = {
        displayName: 'Document Analysis',
        currentDocument: ko.observable(docAnalysisObj.documents[0]),
        documentData: ko.observableArray(docAnalysisObj.documents),
        documentFormatted: ko.observable(),

        $init: $init,
        activate: activate,
        onmouseOver: onmouseOver,
        onmouseOut: onmouseOut,
        mouseClick: mouseClick,
        changeDocument: changeDocument,
        canDeactivate: canDeactivate,
        viewAttached: viewAttached
    };
    return vm;

function changeDocument(newDocument) {
        var self = this;
        // If they clicked the same document, ignore and return
        if (!newDocument || (self.currentDocument() && self.currentDocument().id === newDocument.id)) {
            return;
        }

        // Set the id selector name
        var docElementSelector = '#document-' + newDocument.id;

        // Remove the highlight from the previous class if it exists
        if (self.currentDocument()) {
            $('#document-' + self.currentDocument().id).removeClass('document-selected');
        }
        // Set the document to the new one
        self.currentDocument(newDocument);
        // Use data service to pull the html into self.documentFormatted
        dataservice.getDocument(self.documentFormatted, self.currentDocument().url);

        // Highlight the new current document
        $(docElementSelector).addClass('document-selected');

    }
var getDocument = function (documentObservable, url) {
        documentObservable([]);

        if (!url) {
            console.log('Error: No url provided for document');
            documentObservable('<h1>Error: Document Not Found</h1>Document source was undefined.');
            return;
        }

        url = './app/views/' + url;

        var options = {
            url: url,
            type: 'GET',
            dataType: 'html',
            cache: false,
            error: queryFailed
        };

        return $.ajax(options)
            .then(querySucceeded);

        function querySucceeded(data) {
            console.log('Document \'' + url + '\' retrieval succeeded.');
            documentObservable(data);

            var currentID = 1;
            while (documentObservable().match(/\[selectable\]/g)) {
                documentObservable(documentObservable().replace('[selectable]', '<div class="selectable" selectID="' + currentID + '" data-bind="event: { mouseover: function () { $root.onmouseOver(' + currentID + '); }, mouseout: function () { $root.onmouseOut(' + currentID + '); }, click: function () { $root.mouseClick(' + currentID + '); } }">'));
                currentID++;
            }
        }

        function queryFailed(jqXHR, textStatus) {
            console.log('Error getting document ' + url + ': ' + textStatus);
            documentObservable('<h1>Error: Document Not Found</h1>' + textStatus);
        }

    };
[selectable]
            &bull; This is a sample selectable area. This will be highlighted<br />
            when someone mouses over it.
            <br />[/selectable]