renderizar escape directivas angularjs angularjs-directive ng-controller

escape - ng-bind-html angularjs



La forma más fácil de pasar una variable de ámbito AngularJS de directiva a controlador? (2)

Espere hasta que angular haya evaluado la variable

He tenido muchas vueltas con esto, y no pude hacerlo funcionar incluso con la variable definida con "=" en el alcance. Aquí hay tres soluciones dependiendo de su situación.

Solución n. ° 1

Descubrí que la variable no se evaluó por angular aún cuando se pasó a la directiva. Esto significa que puede acceder y usarlo en la plantilla, pero no dentro de la función del enlace o del controlador de la aplicación, a menos que esperemos a que se evalúe.

Si su variable está cambiando o se obtiene a través de una solicitud, debe usar $observe o $watch :

app.directive(''yourDirective'', function () { return { restrict: ''A'', // NB: no isolated scope!! link: function (scope, element, attrs) { // observe changes in attribute - could also be scope.$watch attrs.$observe(''yourDirective'', function (value) { if (value) { console.log(value); // pass value to app controller scope.variable = value; } }); }, // the variable is available in directive controller, // and can be fetched as done in link function controller: [''$scope'', ''$element'', ''$attrs'', function ($scope, $element, $attrs) { // observe changes in attribute - could also be scope.$watch $attrs.$observe(''yourDirective'', function (value) { if (value) { console.log(value); // pass value to app controller $scope.variable = value; } }); } ] }; }) .controller(''MyCtrl'', [''$scope'', function ($scope) { // variable passed to app controller $scope.$watch(''variable'', function (value) { if (value) { console.log(value); } }); }]);

Y aquí está el html (¡recuerda los corchetes!):

<div ng-controller="MyCtrl"> <div your-directive="{{ someObject.someVariable }}"></div> <!-- use ng-bind in stead of {{ }}, when you can to avoids FOUC --> <div ng-bind="variable"></div> </div>

Tenga en cuenta que no debe establecer la variable en "=" en el alcance, si está utilizando la función $observe . Además, descubrí que pasa objetos como cadenas, por lo que si está pasando objetos, use la solución n. ° 2 o scope.$watch(attrs.yourDirective, fn) (, o n . ° 3 si la variable no está cambiando).

Solución n. ° 2

Si su variable se crea, por ejemplo, en otro controlador , pero solo necesita esperar hasta que angular lo haya evaluado antes de enviarlo al controlador de la aplicación, podemos usar $timeout para esperar hasta que se haya ejecutado $apply . También tenemos que usar $emit para enviarlo al controlador de aplicación de alcance principal (debido al alcance aislado en la directiva):

app.directive(''yourDirective'', [''$timeout'', function ($timeout) { return { restrict: ''A'', // NB: isolated scope!! scope: { yourDirective: ''='' }, link: function (scope, element, attrs) { // wait until after $apply $timeout(function(){ console.log(scope.yourDirective); // use scope.$emit to pass it to controller scope.$emit(''notification'', scope.yourDirective); }); }, // the variable is available in directive controller, // and can be fetched as done in link function controller: [ ''$scope'', function ($scope) { // wait until after $apply $timeout(function(){ console.log($scope.yourDirective); // use $scope.$emit to pass it to controller $scope.$emit(''notification'', scope.yourDirective); }); }] }; }]) .controller(''MyCtrl'', [''$scope'', function ($scope) { // variable passed to app controller $scope.$on(''notification'', function (evt, value) { console.log(value); $scope.variable = value; }); }]);

Y aquí está el html (¡sin corchetes!):

<div ng-controller="MyCtrl"> <div your-directive="someObject.someVariable"></div> <!-- use ng-bind in stead of {{ }}, when you can to avoids FOUC --> <div ng-bind="variable"></div> </div>

Solución n. ° 3

Si su variable no está cambiando y necesita evaluarla en su directiva, puede usar la función $eval :

app.directive(''yourDirective'', function () { return { restrict: ''A'', // NB: no isolated scope!! link: function (scope, element, attrs) { // executes the expression on the current scope returning the result // and adds it to the scope scope.variable = scope.$eval(attrs.yourDirective); console.log(scope.variable); }, // the variable is available in directive controller, // and can be fetched as done in link function controller: [''$scope'', ''$element'', ''$attrs'', function ($scope, $element, $attrs) { // executes the expression on the current scope returning the result // and adds it to the scope scope.variable = scope.$eval($attrs.yourDirective); console.log($scope.variable); } ] }; }) .controller(''MyCtrl'', [''$scope'', function ($scope) { // variable passed to app controller $scope.$watch(''variable'', function (value) { if (value) { console.log(value); } }); }]);

Y aquí está el html (¡recuerda los corchetes!):

<div ng-controller="MyCtrl"> <div your-directive="{{ someObject.someVariable }}"></div> <!-- use ng-bind instead of {{ }}, when you can to avoids FOUC --> <div ng-bind="variable"></div> </div>

Además, eche un vistazo a esta respuesta: https://stackoverflow.com/a/12372494/1008519

Referencia para el problema FOUC (flash de contenido sin estilo): http://deansofer.com/posts/view/14/AngularJs-Tips-and-Tricks-UPDATED

Para el interesado: he aquí un artículo sobre el ciclo de vida angular

¿Cuál es la forma más fácil de pasar una variable de ámbito AngularJS de directiva a controlador? Todos los ejemplos que he visto parecen tan complejos, ¿no hay alguna forma de que pueda acceder a un controlador desde una directiva, y establecer una de sus variables de ámbito?


Editado en 2014/8/25: Here fue donde lo bifurqué.

Gracias @anvarik.

Aquí está el JSFiddle . Olvidé dónde bifurqué esto. Pero este es un buen ejemplo que te muestra la diferencia entre = y @

<div ng-controller="MyCtrl"> <h2>Parent Scope</h2> <input ng-model="foo"> <i>// Update to see how parent scope interacts with component scope</i> <br><br> <!-- attribute-foo binds to a DOM attribute which is always a string. That is why we are wrapping it in curly braces so that it can be interpolated. --> <my-component attribute-foo="{{foo}}" binding-foo="foo" isolated-expression-foo="updateFoo(newFoo)" > <h2>Attribute</h2> <div> <strong>get:</strong> {{isolatedAttributeFoo}} </div> <div> <strong>set:</strong> <input ng-model="isolatedAttributeFoo"> <i>// This does not update the parent scope.</i> </div> <h2>Binding</h2> <div> <strong>get:</strong> {{isolatedBindingFoo}} </div> <div> <strong>set:</strong> <input ng-model="isolatedBindingFoo"> <i>// This does update the parent scope.</i> </div> <h2>Expression</h2> <div> <input ng-model="isolatedFoo"> <button class="btn" ng-click="isolatedExpressionFoo({newFoo:isolatedFoo})">Submit</button> <i>// And this calls a function on the parent scope.</i> </div> </my-component> </div>

var myModule = angular.module(''myModule'', []) .directive(''myComponent'', function () { return { restrict:''E'', scope:{ /* NOTE: Normally I would set my attributes and bindings to be the same name but I wanted to delineate between parent and isolated scope. */ isolatedAttributeFoo:''@attributeFoo'', isolatedBindingFoo:''=bindingFoo'', isolatedExpressionFoo:''&'' } }; }) .controller(''MyCtrl'', [''$scope'', function ($scope) { $scope.foo = ''Hello!''; $scope.updateFoo = function (newFoo) { $scope.foo = newFoo; } }]);