Pourquoi est-ngModel.$setViewValue(...) pas de
Je suis en train d'écrire une directive qui a besoin d'un cas isolé, mais je veux le lier à la portée parent via ngModel.
Ici, le problème est que les parents de la portée de la valeur n'est pas modifiée.
Balisage
<form name="myForm" ng-app="customControl">
<div ng-init="form.userContent"></div>
<div contenteditable name="myWidget" ng-model="form.userContent" required>Change me!</div>
<span ng-show="myForm.myWidget.$error.required">Required!</span>
<hr />
<textarea ng-model="form.userContent"></textarea>
</form>
JS
angular.module('customControl', []).directive('contenteditable', function() {
return {
restrict : 'A', //only activate on element attribute
require : '?ngModel', //get a hold of NgModelController
scope: {},
link : function(scope, element, attrs, ngModel) {
if (!ngModel)
return; //do nothing if no ng-model
//Specify how UI should be updated
ngModel.$render = function() {
element.html(ngModel.$viewValue || '');
};
//Listen for change events to enable binding
element.bind('blur keyup change', function() {
scope.$apply(read);
});
read(); //initialize
//Write data to the model
function read() {
ngModel.$setViewValue(element.html());
}
}
};
});
Démo: Violon.
Cela fonctionne bien si je n'utilise pas un isolé champ d'application de la directive
Démo: Violon.
- Ne devrait pas
element.html(ngModel.$viewValue...)be
element.html($sce.getTrustedHtml(ngModel.$viewValue)..) " je sais que c'est presque exactement la même que dans le ng docs exemple, mais je viens de découvrir cette contourne la protection xss autrement. - Pouvez-vous expliquer pourquoi l'isoler de la portée de faire, il ne fonctionne pas?
- Re @cirrus commentaire, il me semble que pour éviter les attaques de type XSS, que chaque fois que quelque chose est placé dans l'élément qu'il devrait d'abord être désinfectés à l'aide d' $désinfecter (c'est à dire ne pas faire confiance à l'HTML). Quelque chose comme element.html($désinfecter(ngModel.$viewValue))`.
Vous devez vous connecter pour publier un commentaire.
La raison en est que, puisque vous êtes en train de créer un isolé étendue pour votre
contenteditable
directive, lang-model
la directive sur le même élément est que les isolés de la portée de l'. Ce qui signifie que vous avez deux portées différentes qui ne sont pas connectés les uns aux autres, qui ont tous deux unform.userContent
bien que les modifications séparément. Je pense que l'on peut illustrer par le présent code:Comme vous le verrez dans votre console, il y a deux portées différentes et
form.userContent
sur modifier séparément si vous modifiez le texte dans le textarea ou si vous modifiez le texte dans votre contenteditable div.Donc, je parie que vous êtes en train de penser "assez avec l'expliquer et me montrer une solution!". Eh bien, il n'y a pas (à ma connaissance) une jolie solution pour ce faire, mais il y en a un qui fonctionne. Ce que vous voulez faire est de mettre une référence du modèle de votre isolé portée, et assurez-vous qu'il a le même nom dans votre isolé portée qu'à la portée parent.
Voici ce que vous faites, au lieu de créer un vide portée comme ceci:
Vous lier le modèle comme ceci:
Maintenant, vous avez un
model
bien sur votre isolé étendue qui est une référence àform.userContent
sur votre parent. Maisng-model
n'est pas à la recherche d'unmodel
propriété, c'est la recherche d'unform.userProperty
qui n'existent pas dans notre isolé portée. Donc pour remédier à cela, nous ajoutons ceci à l'intérieur de notre fonction de liaison:La première montre se synchronise les modifications sur
form.userContent
qui vient de l'extérieur de notre directive de notre isoléform.userContent
, et la seconde montre fait en sorte que nous propager les modifications sur notre isoléform.userContent
jusqu'à la portée parent.Je me rends compte que c'est une longue réponse, et peut-être pas très facile à suivre. Je serais heureux de clearify tout ce qui vous vous sentez est flou.
ng-model
etcontenteditable
, comment venir vous dire qu'ils ont deux portées différentes? Il ressemble à une contradiction. Ou ai-je raté quelque chose?la première réponse explique le problème, je crois que j'ai une solution plus simple qui évite supplémentaire montres.
pour résumer la réponse 1. ngModel ne peuvent pas travailler à l'intérieur de l'isoler de la portée, car les éléments que vous avez prévu pour le lier à ne sont pas dans son champ d'application. ils sont dans la portée parent.
solution de 1, se lient à la mère de propriété
devient
solution 2, déplacer ngModel à l'extérieur de l'isoler de la portée
require : '?ngModel',
devientrequire : '?^ngModel',
l' ^ dit que votre directive regarder dans les éléments de parent pour ngModeldevient
Je ne suis pas sûr si cela fonctionne pour vous. Cependant, vous pouvez lui donner un essai.
html:
js