2012-05-06 1 views
19

Ein Label-Tag ist von der Form:Mit Ember.js Textfeld-IDs für einen <label> Tag

<label for="id_of_text_field"> 
<input type="text" name="example" id="id_of_text_field" /> 

Wo der for Tag des Etiketts und der id Tag des Textfeldes übereinstimmen müssen. Ich hatte zwei Ideen, diese Arbeit in meiner Ember.js Vorlage zu machen:

Idee # 1: Ich habe versucht, einen spezielle field_id Bindung genannt zu machen in verwenden, um sowohl die label und die TextField. Ich ausgeführt dies wie folgt:

<label {{bindAttr for="content.field_id"}}> {{content.label}}</label> 
{{view Ember.TextField valueBinding="content.data" id="content.field_id"}} 

Leider nur die label's id richtig macht. Die TextField's ID macht nicht rendern richtig und entpuppt sich als "metemorph ... etwas-oder-anderes".

Idee # 2: Irgendwie die TextFields ID zu beschwören und diese für das Etikett-Tag zu verwenden, aber ich fürchte, irgendwann wird die TextFields ID nicht bereit sein, wenn das Etikett-Tag gerendert wird. Auch wenn das kein Problem war, weiß ich nicht, wie man die ID TextField's von JS findet.

Dies ist in einer Vorlage, so dass ich mehr als eines dieser Label/TextField-Paare haben werde.

Wie kann ich die for Markierung des Etiketts mit dem Tag id des TextFields mit Ember.js zusammenbringen?

Vielen Dank!

UPDATE

Peter Wagenet Rat Verwendung und leichte Modifikation, habe ich folgendes:

<label {{bindAttr for="textField.elementId"}}> {{content.label}}</label> 
{{view Ember.TextField valueBinding="content.value" viewName="textField"}} 

dieser Technik Benutzer jetzt Etiketten klicken können Mit Textfeldern auswählen, Kontrollkästchen und wählt.

+1

Für die neueste Ember (1.4.0-beta.6) müssen Sie stattdessen 'for =" view.textField.elementId "' verwenden. – jevon

Antwort

21

Zunächst ist das Metamorph-Tag für den Wert des Labels. Es hängt nicht mit der ID des Feldes zusammen. Dieser Code funktioniert jedoch immer noch nicht, da Standardeigenschaften nichts mit Eigenschaftenpfaden tun. In diesem Fall ist der Wert id buchstäblich content.field_id. Dies ist sicherlich nicht das, was Sie wollten. Unter normalen Umständen könnten Sie elementIdBinding (id ist nur ein Alias ​​für elementId) verwenden, jedoch können die Element-IDs für Ember-Ansichten nach der Erstellung nicht geändert werden, so dass die Vorgehensweise hier nicht funktioniert.

Eine mögliche Lösung nutzt die viewName-Eigenschaft. Die viewName-Eigenschaft bietet einen benannten Verweis auf die Ansicht parentView.Sie könnten dann wie folgt vor:

<label {{bindAttr for="view.textField.field_id"}}> {{content.label}}</label> 
{{view Ember.TextField valueBinding="content.data" viewName="textField"}} 
+1

Ich denke, http://jsfiddle.net/GtsKK/2/ ist eine vollständige Demonstration dessen, was shs anstrebt. Sie möchten "for" an textField.elementId binden, nicht an field_id, da die TextField-Ansicht dieses Attribut nicht enthält. Außerdem können Sie die TextField-Klasse nicht allein verwenden, da ihr name-Attribut nichts bindet, und damit es ein gültiges Formular ist, müssen Sie einen Namen für jede Ihrer Eingaben angeben, also habe ich eine Unterklasse erstellt TextField und fügte die fehlende Namensattributbindung hinzu. –

+0

Entschuldigung für die Änderungen ... also setze ich die Vorlage auf: {{view Ember.TextField valueBinding = "content.data "viewName =" textField "}} und das war's. Die Tags ** für ** und ** ID ** stimmen nun überein. Kein JS erforderlich. Sehr schön! Ich habe Ihre 'field_id' in 'elementId' geändert. Scheint zu einfach. – shs

+0

Nur aus Neugier, wie würde ich 'elternView' aus dem berechneten Wert content.field_id erhalten? Von innen field_id: function() {} Ich versuchte eine Vielzahl von get | getPath() mit 'view', 'this.view', 'parentView', 'this.parentView', und sie alle kamen zurück null oder undefiniert. – shs

1

Hier war meine Lösung für dieses Problem aus einer Weile zurück:

App.Widget.TextField = Em.ContainerView.extend({ 
    tagName: '', 
    type: 'text', 
    label: null, 
    value: null, 
    valueSize: '30px', 

    childViews: ['labelView', 'inputView'], 

    labelView: Em.View.extend({ 
     tagName: 'label', 
     attributeBindings: ['for'], 

     forBinding: 'parentView.inputView.elementId', 

     init: function() { 
      this.set('defaultTemplate', Em.Handlebars.compile(this.getPath('parentView.label'))); 
      this._super(); 
     } 
    }), 

    inputView: Em.TextField.extend({ 
     typeBinding: 'parentView.type', 
     sizeBinding: 'parentView.valueSize', 
     valueBinding: 'parentView.value' 
    }) 
}); 

dann aus einer Vorlage Lenker:

{{view App.Widget.TextField label="Some Label"}} 
5

Dies gewonnen Löse immer dein Problem nicht, aber ich wollte nur hinzufügen, dass das einfache Verschachteln der Eingabe innerhalb des Labels oft eine bequeme Lösung ist, da es dir ermöglicht, das Attribut for ganz zu löschen (reference).

+0

Interessant. Ich hatte geplant, Kontrollen in einer Tabelle mit Etiketten in einer Spalte und Kontrollen in der anderen zu legen. – shs

+0

Weißt du, was der Browser dafür unterstützt? Mit einem schnellen Test scheint es in Firefox und Chrome gut zu funktionieren. Ich habe IE nicht handlich ... –

+0

Ich weiß es nicht. Es scheint jedoch ein allgemeines Muster zu sein, also würde ich annehmen, dass es weit verbreitet ist. –