Ich habe ein Formular, das Markup von Bootstrap verwendet, wie das folgende:
<form class="form-horizontal">
<fieldset>
<legend>Legend text</legend>
<div class="control-group">
<label class="control-label" for="nameInput">Name</label>
<div class="controls">
<input type="text" class="input-xlarge" id="nameInput">
<p class="help-block">Supporting help text</p>
</div>
</div>
</fieldset>
</form>
Es gibt eine Menge Boilerplate-Code, den ich auf eine neue Direktive reduzieren möchte - Formulareingabe wie folgt:
<form-input label="Name" form-id="nameInput"></form-input>
erzeugt:
<div class="control-group">
<label class="control-label" for="nameInput">Name</label>
<div class="controls">
<input type="text" class="input-xlarge" id="nameInput">
</div>
</div>
Ich habe so viel Arbeit über eine einfache Vorlage.
angular.module('formComponents', [])
.directive('formInput', function() {
return {
restrict: 'E',
scope: {
label: 'bind',
formId: 'bind'
},
template: '<div class="control-group">' +
'<label class="control-label" for="{{formId}}">{{label}}</label>' +
'<div class="controls">' +
'<input type="text" class="input-xlarge" id="{{formId}}" name="{{formId}}">' +
'</div>' +
'</div>'
}
})
Wenn ich jedoch erweiterte Funktionen hinzufüge, stecke ich fest.
Wie kann ich Standardwerte in der Vorlage unterstützen?
Ich möchte den Parameter "type" als optionales Attribut in meiner Direktive verfügbar machen, z.
<form-input label="Password" form-id="password" type="password"/></form-input>
<form-input label="Email address" form-id="emailAddress" type="email" /></form-input>
Wenn jedoch nichts angegeben ist, möchte ich standardmäßig auf "text"
. Wie kann ich das unterstützen?
Wie kann ich die Vorlage basierend auf dem Vorhandensein / Fehlen von Attributen anpassen?
Ich möchte auch das Attribut "erforderlich" unterstützen können, wenn es vorhanden ist. Z.B:
<form-input label="Email address" form-id="emailAddress" type="email" required/></form-input>
Wenn required
es in der Direktive vorhanden ist, möchte ich es dem <input />
in der Ausgabe generierten hinzufügen und es ansonsten ignorieren. Ich bin mir nicht sicher, wie ich das erreichen soll.
Ich vermute, dass diese Anforderungen über eine einfache Vorlage hinausgegangen sind und die Vorkompilierungsphasen verwenden müssen, aber ich weiß nicht, wo ich anfangen soll.
quelle
type
dynamisch über Bindung gesetzt wird, z.type="{{ $ctrl.myForm.myField.type}}"
? Ich habe alle folgenden Methoden überprüft und konnte keine Lösung finden, die in diesem Szenario funktioniert. Es sieht so aus, als würde die Vorlagenfunktion Literalwerte der Attribute sehen, z.tAttr['type'] == '{{ $ctrl.myForm.myField.type }}'
statttAttr['type'] == 'password'
. Ich bin verwirrt.Antworten:
quelle
htmlText
Ihnen eine zusätzlicheng-click
irgendwo, wäre die einzige Änderung zu ersetzenelement.replaceWith(htmlText)
mitelement.replaceWith($compile(htmlText))
?htmlText
eine ng-transclude-Direktive enthält$error
Flags für die eingefügte Eingabe werden nie gesetzt. Ich musste dies innerhalb der Verknüpfungseigenschaft einer Direktive tun:$compile(htmlText)(scope,function(_el){ element.replaceWith(_el); });
damit der Controller des Formulars seine neu gebildete Existenz erkennt und in die Validierung einbezieht. Ich konnte es nicht dazu bringen, in der Compile-Eigenschaft einer Direktive zu funktionieren.Ich habe versucht, die von Misko vorgeschlagene Lösung zu verwenden, aber in meiner Situation waren einige Attribute, die in meine HTML-Vorlage eingefügt werden mussten, selbst Anweisungen.
Leider haben nicht alle Anweisungen, auf die in der resultierenden Vorlage verwiesen wird, ordnungsgemäß funktioniert. Ich hatte nicht genug Zeit, um in den Winkelcode einzutauchen und die Grundursache herauszufinden, fand aber eine Problemumgehung, die möglicherweise hilfreich sein könnte.
Die Lösung bestand darin, den Code, der die HTML-Vorlage erstellt, von der Kompilierung in eine Vorlagenfunktion zu verschieben. Beispiel basierend auf Code von oben:
quelle
Die obigen Antworten funktionieren leider nicht ganz. Insbesondere hat die Kompilierungsphase keinen Zugriff auf den Bereich, sodass Sie das Feld nicht basierend auf dynamischen Attributen anpassen können. Die Verwendung der Verknüpfungsstufe scheint die größte Flexibilität zu bieten (in Bezug auf das asynchrone Erstellen von Dom usw.). Der folgende Ansatz befasst sich mit folgenden Aspekten:
Ich habe einen Kern mit vollständigerem Code und einer Beschreibung des Ansatzes erstellt.
quelle
Error: [ngTransclude:orphan] Illegal use of ngTransclude directive in the template! No parent directive that requires a transclusion found.
Folgendes habe ich letztendlich verwendet.
Ich bin sehr neu bei AngularJS und würde gerne bessere / alternative Lösungen sehen.
Anwendungsbeispiel:
quelle
<form-input ng-model="appName" label="Application Name" form-id="appName" required/></form-input>
)compile
Phase, in der die Vorlage transformiert wird, und dielink
Phase, in der die Daten in der Ansicht geändert werden . In diesem Sinne ist der Hauptunterschied zwischen demcompile
undlink
Funktionen , die in den Richtlinien ist , dasscompile
Funktionen befassen sich mit Transformieren der Vorlage selbst, undlink
Funktionen befassen sich mit Herstellung einer dynamischen Verbindung zwischen Modell und Ansicht. Es ist in dieser zweiten Phase die Bereiche an den kompilierten angebracht sindlink
Funktionen, und die Richtlinie wird Live durch Datenbindung "