J'ai un formulaire qui utilise le balisage de Bootstrap, comme le suivant:
<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>
Il y a beaucoup de code standard là-dedans, que j'aimerais réduire à une nouvelle directive - form-input, comme suit:
<form-input label="Name" form-id="nameInput"></form-input>
génère:
<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>
J'ai beaucoup de travail via un modèle simple.
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>'
}
})
Cependant, c'est lorsque j'ajoute des fonctionnalités plus avancées que je suis bloqué.
Comment puis-je prendre en charge les valeurs par défaut dans le modèle?
Je voudrais exposer le paramètre "type" comme attribut facultatif sur ma directive, par exemple:
<form-input label="Password" form-id="password" type="password"/></form-input>
<form-input label="Email address" form-id="emailAddress" type="email" /></form-input>
Cependant, si rien n'est spécifié, j'aimerais utiliser par défaut "text"
. Comment puis-je soutenir cela?
Comment puis-je personnaliser le modèle en fonction de la présence / absence d'attributs?
J'aimerais également pouvoir prendre en charge l'attribut "requis", s'il est présent. Par exemple:
<form-input label="Email address" form-id="emailAddress" type="email" required/></form-input>
Si required
est présent dans la directive, je voudrais l'ajouter au généré <input />
dans la sortie et l'ignorer autrement. Je ne sais pas comment y parvenir.
Je soupçonne que ces exigences ont peut-être dépassé un simple modèle et doivent commencer à utiliser les phases de pré-compilation, mais je ne sais pas par où commencer.
la source
type
est défini dynamiquement via une liaison par exemple.type="{{ $ctrl.myForm.myField.type}}"
? J'ai vérifié toutes les méthodes ci-dessous et je n'ai trouvé aucune solution qui fonctionnera dans ce scénario. On dirait que la fonction de modèle verra les valeurs littérales des attributs, par exemple.tAttr['type'] == '{{ $ctrl.myForm.myField.type }}'
au lieu detAttr['type'] == 'password'
. Je suis perplexe.Réponses:
la source
htmlText
vous en ajoutiezng-click
quelque part, la seule modification serait-elle de remplacerelement.replaceWith(htmlText)
parelement.replaceWith($compile(htmlText))
?htmlText
contient une directive ng-transclude$error
indicateurs sur l'entrée insérée ne sont jamais définis. Je devais le faire dans la propriété link d'une directive:$compile(htmlText)(scope,function(_el){ element.replaceWith(_el); });
pour que le contrôleur du formulaire reconnaisse sa nouvelle existence et l'inclue dans la validation. Je ne pouvais pas le faire fonctionner dans la propriété compile d'une directive.J'ai essayé d'utiliser la solution proposée par Misko, mais dans ma situation, certains attributs, qui devaient être fusionnés dans mon template html, étaient eux-mêmes des directives.
Malheureusement, toutes les directives référencées par le modèle résultant ne fonctionnaient pas correctement. Je n'ai pas eu assez de temps pour plonger dans le code angulaire et découvrir la cause principale, mais j'ai trouvé une solution de contournement, qui pourrait potentiellement être utile.
La solution était de déplacer le code, qui crée le modèle html, de la compilation vers une fonction modèle. Exemple basé sur le code ci-dessus:
la source
Les réponses ci-dessus ne fonctionnent malheureusement pas tout à fait. En particulier, l'étape de compilation n'a pas accès à l'étendue, vous ne pouvez donc pas personnaliser le champ en fonction d'attributs dynamiques. L'utilisation de l'étape de liaison semble offrir le plus de flexibilité (en termes de création asynchrone de dom, etc.) L'approche ci-dessous aborde que:
J'ai créé un résumé avec un code plus complet et une description de l'approche.
la source
Error: [ngTransclude:orphan] Illegal use of ngTransclude directive in the template! No parent directive that requires a transclusion found.
Voici ce que j'ai fini par utiliser.
Je suis très nouveau sur AngularJS, j'aimerais donc voir de meilleures solutions / alternatives.
Exemple d'utilisation:
la source
<form-input ng-model="appName" label="Application Name" form-id="appName" required/></form-input>
)compile
phase, qui traite de la transformation du modèle, et lalink
phase, qui traite de la modification des données dans la vue. Dans ce sens, la principale différence entre lescompile
et leslink
fonctions dans les directives est que lescompile
fonctions traitent de la transformation du modèle lui-même, et leslink
fonctions traitent de l'établissement d'une connexion dynamique entre le modèle et la vue. C'est dans cette deuxième phase que les portées sont attachées auxlink
fonctions compilées , et la directive devient active grâce à la liaison de données "