1
数据绑定后动态绑定外部HTML文件

我一直在寻找和我发现我的有点类似的问题,但没有相当多符合我想要做的(或至少,在解决方案没有为我工作)。我对杜兰达非常陌生,所以我没有线索可以从哪里开始做到这一点。我工作的一个测试应用与我有一个div是数据绑定到,像这样显示HTML:在查看在迪朗达尔

<div class="active-document-text" id="document-text" data-bind="html: documentBody"> 

数据绑定在JavaScript的视图模型,我让它使用AJAX调用来获取外部HTML文件。它工作正常,并正确地绑定到视图,显示文档。我的问题是,外部HTML将在它的一个或多个数据结合,以及:

External.html

Lorem ipsum dolor 
<div class="selectable" id="selectable-1" 
data-bind="event: { click: $parent.onmouseClick }" > 
sit amet, consectetur adipiscing</div> elit. 
Integer nec odio. Praesent libero. Sed cursus ante dapibus diam. 
Sed nisi. Nulla quis sem at nibh elementum imperdiet. 

我想知道我怎么能设定,让这”数据将这些实例绑定到当前视图模型以在那里处理。这个想法是有一个可选的文本区域(简单的鼠标悬停突出显示),并将其与当前选定的索引进行比较。更简单的解释是,它与提供句子的应用程序类似,用户可以单击名词类别,然后在句子中选择名词。如上例所示,可选区域可以在文本中的任何位置。我已经能够获取它来呈现所有的HTML,但是在获得数据绑定的工作方面一直不成功。我试过在knockout data-bind on dynamically generated elements之后尝试应用一个ko.applyBindings(),但我会收到一个未定义的路由器错误,我也试过创建一个合成传递数据,如inserting dynamic html into durandal views,它看起来像外部html会有它拥有.js模型/视图模型。我是否完全错误地进行了这个?可能过度复杂化?最初,我们把它分成了一个模型,其中每一段文本都有一个可选属性,但它真的很笨重,打破了可观的文档和HMTL格式化的噩梦,所以我试图找到一个更优雅的解决方案。我感谢您的帮助!

编辑

了以下问题在这个问题上展开: 是在订购时需要为它纳入事件绑定在外部HTML文件中的长div标签不是非开发人员友好谁很可能是这些文件的创造者。我目前已经通过AJAX调用获取了html文件,然后用long div标签替换了一个简单的自定义'[selectable]'标签并将其存储在可观察对象中,但是我仍然不确定如何将它与绑定到当前视图。

下面是它试图让它工作的当前外观。我在特别重要的行首添加了两个星号。

的观点:

<h3 data-bind="html: displayName"></h3> 
<div class="document-analysis document-analysis-border"> 
    <span class="title-bar">Analyze Documents</span> 
    <img src="./assets/images/arrow_minimize.jpg" class="minimize-button" /> 
    <div class="container"> 
     <div class="document-bar"> 
      <span class="title">Documents to Analyze</span><br /> 
      <img class="arrow-up" src="./assets/images/arrow_up.jpg" alt="Up Arrow" /> 
      <div data-bind="foreach: documentData()" class="documents scroll-bar"> 
       **<div data-bind="event: { click: function() { $parent.changeDocument($data); } }, attr: { id: 'document-' + id }" class="document"> 
        <img data-bind="attr: { alt: title }" src="./assets/images/document_image.gif" class="document-image" /> 
        <span data-bind="text: title" class="document-name"></span> 
       </div> 
      </div> 
      <img class="arrow-down" src="./assets/images/arrow_down.jpg" alt="Down Arrow" /> 
     </div> 
     <div class="inner-container"> 
      <div class="active-document"> 
       **<!--<div class="scroll-bar text" id="document-text" data-bind="compose: { view: currentDocument().url, transition: 'entrance' }"></div>--> 
       **<div class="scroll-bar text" id="document-text" data-bind="compose: { view: documentFormatted, transition: 'entrance' }"></div> 
       <button class="submit">Submit</button> 
      </div> 
      <div data-bind="foreach: bucketData()" class="buckets"> 
       <div data-bind="event: { click: function() { $parent.changeBucket($data); } }" class="bucket"> 
        <img data-bind="attr: { id: 'bucket-' + id, src: image, alt: title }" src="//:0" class="bucket-image" /> 
        <span data-bind="text: title" class="bucket-name"></span> 
       </div> 
      </div> 
     </div> 
    </div> 
</div> 

第一标记行调用点击一个新文档时changeDocument()函数。 第二行和第三行是尝试获取外部文档的工作方式。注释掉的组合工作正常,但我必须使用长标签以便于突出显示mouseOver和mouseOut上的文本。点击主要用于当前的调试。如果他们单击其中一个存储桶(类别),然后单击外部文档中的可选区域,它将检查数据,如果他们选择了正确的文本选择类别,则可以获得积分。

以下是相关信息的视图模型:

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'); 

    } 

鼠标悬停及移出真的只是添加和删除CSS类鼠标悬停在可选择的区域时。 changeDocument()是我尝试使用以下dataservice对象加载html并处理CSS更改。

DataService在对象:

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); 
     } 

    }; 

DataService是否已肉和本土豆。它加载html并用将用于数据绑定的长标签替换[selectable]的所有匹配项。 我还没有实现结束标记的替换,但这是一件简单的事情。 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已被替换[可选]标签,使其更容易对人基本的HTML技能来构建一个样本文件。

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

回答

3

我不会使用knockoutjs html绑定。

取而代之,使用durandals组合绑定将新元素插入到dom中。 Durandal也会为你处理绑定。

看到这篇文章: http://durandaljs.com/documentation/Using-Composition/

+0

这非常适合我。我结束了使用$ root的事件在外部HTML中的数据绑定,它的工作就像一个魅力。谢谢你的帮助,埃文! –

+0

看来我仍然有这个问题。向老板介绍新解决方案后,他不喜欢为了将事件绑定合并到外部html文件而需要的长div标签。这是因为非开发人员可能会创建这些外部文档。我目前已经通过AJAX调用获取了html文件,然后用long div标签替换了一个简单的自定义'[selectable]'标签并将其存储在可观察对象中,但是我仍然不确定如何将它与绑定到当前视图。任何想法我可以从这里去?我很难过。 –

+0

你可以张贴一些代码,也可以看看你想要的样子 –