2015-05-19 14 views
6

Ich habe seltsames Verhalten, wenn Daten ein Objekt mit einem Formular verknüpfen, das mich dazu brachte, erneut zu hinterfragen, was genau Daten gebunden sind?JsViews, wie Datenbindung sowohl auf dem Root-Objekt als auch auf den verschachtelten Eigenschaften vorgenommen wird?

Grundsätzlich habe ich ein Formular, das neue Firmen erstellt sowie sie aktualisiert. Die eigentliche Erstellung/Aktualisierung erfolgt über Ajax, weshalb ich für beide Zwecke das gleiche Formular verwende. Wenn ich ein Unternehmen gründen muss, funktioniert alles wie erwartet. Wenn ich jedoch ein Unternehmen aktualisieren muss, funktionieren die Dinge nicht so, wie ich es von ihnen erwarte. Bitte sehen Sie sich den folgenden Code an.

Hier ist mein Beispielformular HTML ist:

<div id="result"></div> 

<script type="text/x-jsrender" id="CompanyFormTemplate"> 
    <form> 
     <input type="text" data-link="Company.Name" /> 
    </form> 
</script> 

Hier ist mein Javascript-Code:

var app = new CompanyFormContext(); 

function CompanyFormContext() { 
    this.Company = { 
     Name: '' 
    }; 

    this.setCompany = function (company) { 
     if (company) { 
      $.observable(this).setProperty('Company', company); 
     } 
    }; 
}; 

$(function() { 
    initPage(); 

    ... 

    if (...) { 
     // we need to update company information 

     app.setCompany({ Name: 'Company ABC' }); 
    } 
}); 

function initPage() { 
    var template = $.templates('#CompanyFormTemplate'); 
    template.link("#result", app); 
} 

Anstelle der Formulareingabe zeigt 'Firma ABC', ist es leer. Wenn ich jedoch etwas darin eingebe, ändert sich der Company.Name Wert! Aber während ich möchte, dass die Dateneingabe an die Name-Eigenschaft meines Company-Objekts gebunden wird, möchte ich auch wissen, dass Änderungen am (übergeordneten) Company-Objekt vorgenommen werden und die Datenbindung an die Name-Eigenschaft entsprechend aktualisiert wird.

Also meine Frage ist, wie sollte ich ändern, wie ich diesen Code schreibe, so dass ich eine Datenbindung sowohl auf das Stammobjekt als auch die Eigenschaft erreichen kann?

Antwort

3

Das Problem, das Sie hatten, war, weil Sie in Ihrem Szenario Pfade wie Company.Name haben, für die Sie nicht nur Änderungen der Blatteigenschaft, sondern auch Änderungen beim Ersetzen von Objekten höher im Pfad (in in diesem Fall die Firma).

Dafür müssen Sie die Syntax data-link="Company^Path" verwenden.

finden Sie im Abschnitt Pfade: Blatt Änderungen oder tiefgreifende Veränderungen in dieser Dokumentation Thema: http://www.jsviews.com/#[email protected].

Siehe auch die Beispiele wie Beispiel: JsViews mit einfachen Objekten und Array in diesem Thema: http://www.jsviews.com/#explore/objectsorvm.

Hier ist ein Update Ihrer jsfiddle, mit dieser Syntax: https://jsfiddle.net/msd5oov9/2/.

BTW, FWIW, in Ihrem fix {^{for}} verwenden Sie haben nicht eine zweite Vorlage verwenden - Sie könnten alternativ geschrieben haben:

<form class="form-horizontal"> 
    {^{for Company}} 
     ... 
     <input type="text" data-link="Name" /> 
    {{/for}} 
</form> 

auch unten in Ihrem Kommentar zu Ihrer Follow-up-Frage zu antworten Sie können ein beliebiges "Block" -Tag mit einer Vorlage verknüpfen. Wenn Sie tmpl=... für das Tag verwenden, haben Sie sich entschieden, den Inhalt des Blocks in eine separate wiederverwendbare Vorlage zu trennen. (Ein "Teil", wenn Sie so wollen). Der Datenkontext für diese Vorlage ist der gleiche wie im Block.

Also, {{include}} {{if}} und {{else}} Tags verschieben nicht den Datenkontext, aber {{for}} und {{reps}} tun. Mit benutzerdefinierten Tags können Sie entscheiden ...

Also in Ihrem Fall könnten Sie entweder {^{for Company tmpl=.../}} oder {{include tmpl=.../}} aber im zweiten Fall Ihre andere Vorlage verwenden, die Sie verwenden würden Referenz <input type="text" data-link="Company^Name" /> statt <input type="text" data-link="Name" />.

Hier sind einige relevante Links:

+0

Vielen Dank für die Links zu den entsprechenden Abschnitten zu teilen! Ironischerweise war ich in der Vergangenheit beide Abschnitte durchgegangen, aber als ich diesen Code schrieb, fiel mir einfach nicht ein, dass ich das tun musste. Eine kleine Frage: Gibt es ein anderes Konstrukt, das ich verwenden sollte, um anzuzeigen, dass ein Objekt mit der Schablone X anstatt für ein Objekt gerendert wird? –

1

Ich entdeckte einen Weg, dies zu erreichen. Es mag auf den ersten Blick kompliziert erscheinen, aber es wird Sinn ergeben, wenn Sie es erst einmal richtig verstanden haben.

(PS: Ich möchte ein Beispiel wie das war, ich könnte nur darüber bloggen..)

HTML-Code:

<script type="text/x-jsrender" id="CompanyFormTemplate"> 
    <form> 
     {^{for Company tmpl="#CompanyDetailsTemplate" /} 
    </form> 
</script> 

<script type="text/x-jsrender" id="CompanyDetailsTemplate"> 
    <input type="text" data-link="Name" /> 
</script> 

Javascript: Keine von Code über notwendige Änderungen.


Okay, so wie ich sagte, könnte die Lösung kompliziert aussehen, aber es stellt sich heraus, alles, was ich tun musste, war, um wirklich Datensatz verbindliche zuerst auf dem Firmenobjekt, und dann ist es an der Eigenschaft Objekte. Ich frage mich, ob es eine elegantere Lösung gibt (d. H. Eine, in der all dies in einer einzigen Vorlage erreicht werden kann), aber diese Lösung stellt sicher, dass die Datenbindung sowohl am übergeordneten Objekt als auch an dessen Eigenschaften stattfindet.

Ich habe eine JsFiddle für diese Lösung geschrieben, also wenn jemand auf dieses Problem stößt und verstehen möchte, wie diese Lösung für ihr spezielles Problem funktionieren würde, werden sie in der Lage sein, mit einer funktionierenden Lösung zu spielen.