2014-03-04 60 views
1

我正在尋找實現Angular,Knockout或其他數據綁定向導式應用程序的概念證明概念(無服務器端代碼)。不過,當我克隆數據綁定的div時,我似乎打破了數據綁定。數據綁定,同時操縱DOM不與Angular,Knockout一起工作

應用程序的前幾個步驟會捕獲數據,而後面的步驟會將數據呈現給用戶以確認輸入的內容。我按下'next'時插入適當的步驟操作DOM,當按'previous'時取出最後一步。我使用detatchcloneremove這樣做。

任何人都可以提供建議,他們將採取的做法,以及我應該看看什麼框架?

下面是僞代碼給出了一個結構的想法。僞數據綁定代碼就是我認爲它可以工作的原因,我沒有被納入任何框架。

HTML查看

<div id="wizard"> 
    <div id="step1">Enter your name: <input type="text" id="name" /></div> 
</div> 
<div id="actions"><input type="button" value="Previous" /><input type="button" value="Next" onClick="goNext();" /></div> 

<div id="steps"> 
    <div id="stepA">Enter your age: <input type="text" id="age" databind="theAge" /></div> 
    <div id="stepB">The age you entered - {{ theAge }} is too young!</div> 
    <div id="stepC">Enter your favourite colour: <input type="text" id="faveColour" databind="faveCol" /></div> 
    <div id="stepD">Hi {{ name }}. You are {{ age }} years old and your favourite colour is {{ faveCol }}</div> 
</div> 

的JavaScript

<script> 
function goNext() { 
    // figure out which step is next 
    insertStepIntoWizard(step, index, title); 
} 

function insertStepIntoWizard(step, index, title) { 
    var element = step.detach(); 
    wizard.steps('insert', index, { 
     title: title, 
     content: element.clone() 
    }); 
    console.log('insertStepIntoWizard - just inserted ' + step.attr('id') + ' into wizard position ' + index); 
} 
</script> 
+0

你能不能讓你的問題簡潔,讓我們可以在它看看 – dreamweiver

回答

0

我想你的想法是讓你的view反映你的實體model,這基本上是模板。如果您打算使用Knockout/Angular,請考慮使用它的view model來管理頁面狀態/流量/操作,以及控制實體。 (編寫jQuery代碼來查詢DOM和克隆,顯示/隱藏等並不好玩)。 @sabithpocker提出了類似的觀點。

工作示例:我熟悉的淘汰賽,並創建了一個例子您的方案的jsfiddle:http://jsfiddle.net/overflew/BfRq8/5/

注:

  • 我使用template標籤的房子嚮導的每個部分,並且所有步驟都指向視圖模型中的同一模型/實體。
  • 強調綁定的發佈/訂閱性質發生了什麼:
    • 用戶輸入也在頁面底部中繼。
    • 表單標題是動態的,還有「一步」
    • ko.computed是用來「計算」的全名,如果有任何「階梯」向左走
  • Knockout-具體:注意到在這個地方出現括號。如果您選擇學習淘汰賽,偶爾會遇到這種情況。這僅表示您正在評估綁定容器以獲取值。

視圖模型

<div> 
    <h3 data-bind="text: currentStep().name"></h3> 
    <div data-bind="template: { name: 'wizard-step1' }, visible: currentStep().id === 0"></div> 
    <div data-bind="template: { name: 'wizard-step2' }, visible: currentStep().id === 1"></div> 
    <div data-bind="template: { name: 'wizard-step3' }, visible: currentStep().id === 2"></div> 
    <input type="button" value="Next step" data-bind="click: onNext, visible: hasNextSteps" /> 
    <input type="button" value="Submit" data-bind="click: onSubmit,visible: !hasNextSteps()" /> 
    <div data-bind="visible: submitResultMessage, text: submitResultMessage"></div> 
</div> 

<div> 
    <h3>Your inputs</h3> 
    <div data-bind="visible: questions.fullName">Full name: <span data-bind="text: questions.fullName"></span></div> 
    <div data-bind="visible: questions.age">Age: <span data-bind="text: questions.age"></span> 
    </div> 
    <div data-bind="visible: questions.favouriteColour">Favourite colour: <span data-bind="text: questions.favouriteColour"></span> 
    </div> 
</div> 

<script type="text/html" id="wizard-step1"> 
    <div> 
     First name: <input data-bind="value: questions.firstName, valueUpdate:'afterkeydown'" /> 
    </div> 
    <div> 
     Last name: <input data-bind="value: questions.lastName, valueUpdate:'afterkeydown'" /> 
    </div> 
</script> 

<script type="text/html" id="wizard-step2"> 
    <div> 
     Age: <input data-bind="value: questions.age, valueUpdate:'afterkeydown'" /> 
    </div> 
</script> 

<script type="text/html" id="wizard-step3"> 
    <div> 
     Favourite colour: <input data-bind="value: questions.favouriteColour, valueUpdate:'afterkeydown'" /> 
    </div> 
</script> 

查看

// Entity for holding form data. 
var FormData = function() { 
    var self = this; 

    self.firstName = ko.observable(""); 
    self.lastName = ko.observable(""); 
    self.age = ko.observable(""); 
    self.favouriteColour = ko.observable(""); 

    self.fullName = ko.computed(function() {   
     if (!self.firstName() && !self.lastName()) { 
      return ""; 
     } 

     return self.firstName() + " " + self.lastName(); 
    }); 
} 

// Quick handling for managing steps of the wizard 
var wizardSteps = [ 
    { id: 0, name: "Wizard step 1"}, 
    { id: 1, name: "More questions"}, 
    { id: 2, name: "Last step"} 
    ]; 

var ViewModel = function() { 
    var self = this; 

    // Properties 
    self.questions = new FormData(); 

    self.currentStep = ko.observable(wizardSteps[0]); 

    self.submitResultMessage = ko.observable(); 

    // Actions 
    self.onNext = function() { 
     var currentIndex = self.currentStep().id; 

     if (self.hasNextSteps()) { 
      // Move forward one step on the wizard 
      self.currentStep(wizardSteps[currentIndex + 1]); 
     } 
    }; 

    self.onSubmit = function() { 

     self.submitResultMessage("Data is now submitted "); 
    }; 

    // Page control 
    self.hasNextSteps = ko.computed(function() { 
     var currentIndex = self.currentStep().id; 

     return currentIndex < wizardSteps.length - 1; 
    }); 

}; 

ko.applyBindings(new ViewModel()); 
0

最令最前沿的JavaScript框架正在試圖做的是試圖管理在目前的應用中的代碼量龐大在客戶端使用javascript實現了大量的業務邏輯。所以他們主要是試圖爲您提供一些architecture來組織您的代碼,以便於管理,閱讀和擴展。

在你的情況下,你試圖忽略像MVCMVWhatever這樣的體系結構,他們提供和使用該框架來做一些模板,如果我理解正確。爲此,您可以更好地獲取JavaScript中的某些模板引擎的幫助,如handlebars,並使用它來手動呈現存儲在當前JavaScript應用中的數據。

看到這裏http://handlebarsjs.com/

0

只需重新初始化您的綁定。 這解決了我在使用淘汰賽時遇到的問題。

當您更改實際爲MVVM引用的主DOM元素時,會發現任何更改或重構該元素都會妨礙dom關係。 最終,雖然該項目的位置看起來相同,但在技術上,在Java腳本引擎中不是。所以問題就出現了。

爲了解決這樣的問題,只需要一個構造函數,它將初始化或重新初始化DOM中特定元素的映射。

希望能夠解決您的問題。

例子:

的功能可以被稱爲每次,你覺得重新初始化綁定的需要。調用該函數將刪除ID爲「userDetails」的元素的任何綁定,然後可調用applyBindings來初始化綁定。這將調用任何新/更改元素的綁定。

+0

感謝這個Anubhav,這聽起來完全像我所需要的。你能夠提供一個簡短的代碼示例或鏈接,因爲我很難找到有關重新初始化Knockout綁定的信息嗎? – Delorian

+0

@Delorian你可以看看添加的例子 –