J'essaie de créer une directive qui créerait un champ d'entrée avec le même modèle ng que l'élément qui crée la directive.
Voici ce que j'ai trouvé jusqu'à présent:
HTML
<!doctype html>
<html ng-app="plunker" >
<head>
<meta charset="utf-8">
<title>AngularJS Plunker</title>
<link rel="stylesheet" href="style.css">
<script>document.write("<base href=\"" + document.location + "\" />");</script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.2/angular.js"></script>
<script src="app.js"></script>
</head>
<body ng-controller="MainCtrl">
This scope value <input ng-model="name">
<my-directive ng-model="name"></my-directive>
</body>
</html>
Javascript
var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope) {
$scope.name = "Felipe";
});
app.directive('myDirective', function($compile) {
return {
restrict: 'E',
scope: {
ngModel: '='
},
template: '<div class="some"><label for="{{id}}">{{label}}</label>' +
'<input id="{{id}}" ng-model="value"></div>',
replace: true,
require: 'ngModel',
link: function($scope, elem, attr, ctrl) {
$scope.label = attr.ngModel;
$scope.id = attr.ngModel;
console.debug(attr.ngModel);
console.debug($scope.$parent.$eval(attr.ngModel));
var textField = $('input', elem).
attr('ng-model', attr.ngModel).
val($scope.$parent.$eval(attr.ngModel));
$compile(textField)($scope.$parent);
}
};
});
Cependant, je ne suis pas sûr que ce soit la bonne façon de gérer ce scénario, et il y a un bogue selon lequel mon contrôle n'est pas initialisé avec la valeur du champ cible ng-model.
Voici un Plunker du code ci-dessus: http://plnkr.co/edit/IvrDbJ
Quelle est la bonne façon de gérer cela?
EDIT : Après avoir supprimé le ng-model="value"
du modèle, cela semble fonctionner correctement. Cependant, je garderai cette question ouverte parce que je veux vérifier que c'est la bonne façon de procéder.
scope
et le définissez surscope: false
? Comment se lierng-model
dans ce cas?Réponses:
EDIT : Cette réponse est ancienne et probablement obsolète. Juste un avertissement pour ne pas induire les gens en erreur. Je n'utilise plus Angular donc je ne suis pas en bonne position pour apporter des améliorations.
C'est en fait une assez bonne logique mais vous pouvez simplifier un peu les choses.
Directif
HTML avec directive
CSS
Vous pouvez le voir en action avec ce Plunker .
Voici ce que je vois:
EDIT Comme mentionné par Mark dans son commentaire, il n'y a aucune raison pour que vous ne puissiez pas utiliser ng-model, juste pour respecter la convention.
En général, vos directives doivent utiliser la portée isolée (ce que vous avez fait correctement) et utiliser la portée de type '=' si vous voulez qu'une valeur dans votre directive soit toujours mappée à une valeur dans la portée parent.
la source
contenteditable
exemples directive dans la documentation angulaire - page des formulaires , page NgModelController - à la fois l' utilisation modèle ng. Et la page ngModelController dit que ce contrôleur est "destiné à être étendu par d'autres directives".hg-model
(et non la question du couplage, IMO). De cette façon, le contexte de données utilise toujours ng-model, qu'il s'agisse d'<input>
une directive personnalisée ou personnalisée, simplifiant ainsi la surcharge cognitive pour le rédacteur HTML. C'est-à-dire que cela évite au rédacteur HTML d'avoir à trouver le nommy-directive-var
de chaque directive, d'autant plus qu'il n'y a pas de saisie semi-automatique pour vous aider.ng-model-options
ou avec les autres choses du modèle ng, n'est-ce pas?J'ai pris un combo de toutes les réponses, et j'ai maintenant deux façons de le faire avec l'attribut ng-model:
Afficher l'extrait de code
Je ne suis pas sûr que j'aime la compilation au moment du lien. Cependant, si vous remplacez simplement l'élément par un autre, vous n'avez pas besoin de le faire.
Dans l'ensemble, je préfère le premier. Définissez simplement la portée
{ngModel:"="}
et définissezng-model="ngModel"
où vous le souhaitez dans votre modèle.Mise à jour : j'ai inséré l'extrait de code et l'ai mis à jour pour Angular v1.2. Il s'avère que la portée d'isoler est toujours la meilleure, en particulier lorsque vous n'utilisez pas jQuery. Cela se résume donc à:
Remplacez-vous un seul élément: remplacez-le simplement, laissez la portée seule, mais notez que replace est déconseillé pour la v2.0:
Sinon, utilisez ceci:
la source
ng-model
dans une portée isolée?ce n'est pas si compliqué: dans votre dirctive, utilisez un alias:
scope:{alias:'=ngModel'}
dans votre html, utilisez comme d'habitude
la source
Vous n'avez besoin de ng-model que lorsque vous devez accéder à $ viewValue ou $ modelValue du modèle. Voir NgModelController . Et dans ce cas, vous utiliseriez
require: '^ngModel'
.Pour le reste, voir la réponse de Roys .
la source
^
devrait être là uniquement si le modèle ng est appliqué dans un élément parentC'est une petite réponse tardive, mais je l' ai trouvé génial ce post à propos
NgModelController
, que je pense est exactement ce que vous recherchez.TL; DR - vous pouvez utiliser
require: 'ngModel'
puis ajouterNgModelController
à votre fonction de liaison:De cette façon, aucun piratage n'est nécessaire - vous utilisez le module intégré d'Angular
ng-model
la source
Je ne définirais pas le ngmodel via un attribut, vous pouvez le spécifier directement dans le modèle:
plunker : http://plnkr.co/edit/9vtmnw?p=preview
la source
Depuis Angular 1.5, il est possible d'utiliser des composants. Les composants sont le chemin à parcourir et résout ce problème facilement.
Dans YourController, tout ce que vous devez faire est de:
la source
input ng-model="$ctrl.ngModel"
et il se synchronisera également avec $ ctrl.result.La création d'une étendue isolée n'est pas souhaitable. J'éviterais d'utiliser l'attribut scope et ferais quelque chose comme ça. scope: true vous donne une nouvelle portée enfant mais pas un isolat. Utilisez ensuite l'analyse pour pointer une variable de portée locale vers le même objet que l'utilisateur a fourni à l'attribut ngModel.
la source