簡體   English   中英

在Durandal中進行數據綁定后動態綁定外部html文件

[英]Dynamically binding an external html file after the data-bind in Durandal

我一直在尋找,並且我發現了一些類似於我的問題,但沒有一個與我想要做的完全匹配(或者至少,解決方案對我沒有用)。 我是Durandal的新手,所以我不知道從哪里開始實現這一目標。 我正在研究一個測試應用程序,我有一個數據綁定的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.

我想知道如何設置它以便它將這些實例數據綁定到當前的viewmodel以進行處理。 我們的想法是擁有一個可選擇的文本區域(簡單的鼠標懸停突出顯示),並將其與當前選定的索引進行比較。 一個更簡單的解釋是,它類似於提供句子的用戶,用戶點擊名詞類別,然后在句子中選擇名詞。 如上例所示,可選區域可以是文本中的任何位置。 我已經能夠讓它渲染所有的html,但是在使數據綁定工作方面卻沒有成功。 我已經嘗試在動態生成的元素上按照敲除數據綁定應用ko.applyBindings(),但是我會收到一個未定義的路由器錯誤,我也嘗試過創建一個組合傳遞數據,如插入動態html到durandal視圖 ,它看起來像外部HTML將擁有它自己的.js模型/ viewmodel。 我完全錯誤地采取了這種方式嗎? 或許過度復雜化了嗎? 最初,我們把它分解成一個模型,其中每個文本部分都有一個可選擇的屬性,但它真的很笨重地分解了大量的文檔和HMTL格式化的噩夢,所以我試圖找到一個更優雅的解決方案。 我感謝您的幫助!

編輯

以下問題擴展了這個問題:為了將事件綁定合並到外部html文件中所需的long div標簽對於可能是文檔創建者的非開發人員來說並不友好。 我現在再次使用AJAX調用抓取html文件然后用長div標簽替換一個簡單的自定義'[selectable]'標簽並將其存儲在一個observable中,但我仍然不確定如何將其與綁定到當前視圖。

以下是嘗試使其正常工作的當前外觀。 我在特別重要的線的開頭添加了雙星號。

風景:

<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上突出顯示文本。 點擊主要用於此刻的調試。 如果他們單擊其中一個存儲桶(類別),然后單擊外部文檔中的可選區域,則會檢查數據,如果他們為文本選擇選擇了正確的類別,則會獲得積分。

這是相關的viewmodel信息:

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

    }

mouseOver和mouseOut實際上只是在鼠標懸停在可選區域時添加和刪除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);
        }

    };

數據服務是這方面的佼佼者。 它加載html並將所有出現的[selectable]替換為將用於數據綁定的long標記。 我還沒有實現結束標簽的替換,但這很簡單。 div使用自定義屬性selectID而不是ID的原因是因為老板說使用ID是一個壞主意,因為它們可以在文檔中重復,而自定義屬性不太可能發生。

和樣本文件:

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

已經用[selectable]標簽替換了長div,使具有基本HTML技能的人更容易構建示例文檔。

最終,目標是為創建文檔的人提供一個易於使用的標記,而不必嘗試粘貼長標記並跟蹤其個人ID。 我想將鼠標事件與視圖模型聯系起來,因為它是完全相同的活動(並且所有文檔的點將被計算在一起以獲得最終得分)。 從用戶的角度來看,當他們將鼠標懸停在可選文本上時,它應該只是改變顏色(簡單的jQuery)。 如果他們點擊它,它將檢查他們是否選擇了正確的類別(我已經有了這個工作)。 我當前的問題是進行文本替換,並能夠將事件綁定到視圖的函數。

我不會使用knockoutjs html綁定。

而是使用durandals組合綁定以將新元素插入到dom中。 Durandal也將為您處理綁定。

請參閱此文章: http//durandaljs.com/documentation/Using-Composition/

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM