Je déplace ma base de code héritée vers la nouvelle architecture de composants promue avec AngularJS 1.5. J'ai rencontré un problème lors de cette opération pour les formulaires plus volumineux. Traditionnellement, je joignais la validation du formulaire comme suit:
<form name="myForm">
<input type="text" name="input1" ng-model="vm.input1" required />
<div ng-messages="myForm.input1.$error">
<div ng-message="required">Please fill out this field.</div>
</div>
<!-- many more inputs -->
</form>
Lors de la transition vers une architecture de composant, je dois passer explicitement le formulaire au composant:
<form name="vm.myForm">
<my-awesome-input-component model="vm.input1" form="vm.myForm"><my-awesome-input-component>
<!-- many more inputs -->
</form>
Je voudrais éviter de polluer le vm
avec mon formulaire. Existe-t-il un meilleur moyen de réaliser l'architecture de composant souhaitée pour les formulaires?
Mise à jour - changé nom-formulaire en référence-formulaire, car il n'était pas explicite que nous transmettions le formulaire réel référence et pas seulement le nom du formulaire. Cela peut être appelé comme vous le souhaitez, soyez clair sur ce que c'est réellement.
Comme le dit Iain Reid, vous n'avez pas besoin d'utiliser vm pour cela. Vous nommez simplement le formulaire comme vous le souhaitez, puis passez ce nom à votre composant, il ressemblerait à ceci:
<form name="myForm" ng-submit="ctrl.someFunction()" novalidate>
<my-input form-reference="myForm"></my-input>
<button type="submit">Some button</button>
</form>
Assurez-vous que vous écrivez "novalidate" dans votre formulaire pour désactiver les validations par défaut du navigateur, si vous souhaitez gérer les validations par vous-même (ce que je pense que vous utilisez en utilisant des messages ng).
Puis à partir de là, sur mon composant j'écrirais quelque chose comme:
angular.module("myApp")
.component("myInput",{
templateUrl:'path/to/template.html'
bindings:{
formReference:'<',
myInputModel:'<',
onUpdate:'&'
},
controller: MyInputController
}
Et puis dans le modèle d'entrée:
<input type="text" name="myInput" ng-model="$ctrl.myInputModel" ng-change="$ctrl.update($ctrl.myInputModel)" required />
<div ng-messages="$ctrl.formReference.myInput.$error">
<div ng-message="required">Please fill out this field.</div>
</div>
Quelques notes supplémentaires sur les liaisons et comment passer et mettre à jour les modèles:
Donc, dans le contrôleur d'entrée, j'écrirais quelque chose comme:
function MyInputController(){
var ctrl = this;
ctrl.update = function(value){
ctrl.onUpdate({value: value});
};
}
Et enfin, quand j'utilise mon composant dans un formulaire:
<form name="myForm" ng-submit="ctrl.someFunction()" novalidate>
<my-input form-reference="myForm" my-input-model="ctrl.anyModelIWant" on-update="ctrl.updateMyInput(value)"></my-input>
<button type="submit">Some button</button>
</form>
Et le contrôleur du formulaire aurait une fonction:
...
ctrl.updateMyInput = function(value){
ctrl.anyModelIWant = value;
}
...
Documents officiels: https://docs.angularjs.org/guide/component
J'espère que tout cela aide quelqu'un là-bas :-)
Voici une autre approche que certains peuvent trouver utile. Utilisez require
pour inclure le parent form
dans votre $ctrl
:
angular.module("myApp")
.component("myInput",{
templateUrl:'path/to/template.html'
bindings:{
myInputModel:'<',
onUpdate:'&'
},
controller: MyInputController,
require: {
form: '^form'
}
}
Dans le modèle d'entrée:
<input type="text" name="myInput" ng-model="$ctrl.myInputModel" ng-change="$ctrl.update($ctrl.myInputModel)" required />
<div ng-messages="$ctrl.form.myInput.$error">
<div ng-message="required">Please fill out this field.</div>
</div>
Pas besoin de passer le formulaire explicitement dans votre composant car form
est automatiquement ajouté à votre $ctrl
:
<form name="myForm" ng-submit="ctrl.someFunction()" novalidate>
<my-input my-input-model="ctrl.anyModelIWant" on-update="ctrl.updateMyInput(value)"></my-input>
<button type="submit">Some button</button>
</form>
Je suppose que techniquement, vous polluez toujours votre VM, mais au moins vous n'avez pas à le transmettre explicitement dans toute votre hiérarchie.
Ajout de texte pour satisfaire aux exigences d'édition de 6 caractères, période modifiée en virgule pour corriger l'exemple. La période est déroutante pour les nouveaux arrivants.