versiones tutorial que programacion entre ejemplos controladores comunicacion javascript angularjs angularjs-1.5

javascript - tutorial - ¿Por qué mis enlaces de componentes no están definidos en su controlador?



use $rootscope in controller (9)

Estoy escribiendo un componente angular simple. Estoy pasando un parámetro como un enlace y visualizo su valor en la pantalla. Todo funciona bien: puedo ver el parámetro que se muestra en la pantalla.

Componente:

var app = angular.module("test", []); app.component("test", { bindings: { "contactId": "<" }, controllerAs: "model", controller: () => { //output: ''contact id from controller: undefined'' console.log(`contact id from controller: ${this.contactId}`); }, template: "<div>Contact id from view: {{model.contactId}}</div>" });

HTML:

<test contact-id="8"></test>

Sin embargo, cuando intento acceder al enlace desde el controlador (consulte console.log), el valor del enlace undefined está undefined . No entiendo cómo puede estar disponible en la vista, pero no en el controlador.

¿Qué estoy haciendo mal?

Aquí hay un plnkr ilustra el problema.


Asegúrese de utilizar guiones para los enlaces en HTML y camelCase para los enlaces en Javascript.

app.component("test", { bindings: { "myContactId": "<" } } <test my-contact-id="8"></test>

Eso es lo que siempre me olvido de hacer.


Cuando se utilizan componentes angulares, hay un punto en el que el controlador no se ha conectado a través del enlace interno. Si está intentando hacer esto en el constructor de su controlador, no ha sido vinculado a los enlaces. La API de componentes expone algunos ganchos de ciclo de vida que puede definir que se activarán en determinados momentos. Estás buscando el gancho $onInit .

$ onInit (): se invoca en cada controlador después de que todos los controladores de un elemento se hayan construido y se hayan inicializado sus enlaces (y antes de las funciones de enlace pre y post para las directivas de este elemento). Este es un buen lugar para poner código de inicialización para su controlador.

por documentos: https://docs.angularjs.org/guide/component


El valor de contactId está disponible en el $scope en su controlador:

var app = angular.module("test", []); app.component("test", { bindings: { "contactId": "<" }, controllerAs: "model", controller: ($scope) => { var model = $scope.model; alert(`contact id from controller: ${model.contactId}`); }, template: "<div>Contact id from view: {{model.contactId}}</div>" });

Enlace a otra versión de su Plunker here .


Hay dos problemas con el código que causa el error "indefinido".

  1. Como se indicó anteriormente, primero se debe alcanzar el gancho del ciclo de vida $ onInit, el onInit se activa cuando se han realizado todos los enlaces.

De la documentación oficial: documentación de https://docs.angularjs.org/guide/component

$ onInit (): se invoca en cada controlador después de que todos los controladores de un elemento se hayan construido y se hayan inicializado sus enlaces (y antes de las funciones de enlace pre y post para las directivas de este elemento). Este es un buen lugar para poner código de inicialización para su controlador.

  1. El segundo problema que probablemente tendrá es que su controlador no alcanzará el gancho de ciclo de vida cuando use la notación de flecha "() =>" como parámetro para la función del controlador.

El problema es que la notación de flecha no tendrá su propio alcance, sino que usará su alcance envolvente. Lo que significa que cuando se usa "this" se referirá al objeto de la ventana en lugar del componente. Entonces, llamar a esto. $ OnInit () se llamará en la ventana, y no se disparará, porque no existe en la ventana.


La palabra clave this no parece funcionar con la función de flecha, esto funciona con

controller: function() { alert(''contact id from controller: '' + this.contactId); }

Cuando se utiliza la función de flecha, esto parece referirse al objeto de la ventana porque

Una función de flecha no crea su propio contexto, sino que captura el valor de este del contexto envolvente


Para aquellos que usan Directivas, donde se supone que los Componentes, si se especifican enlaces {}, parece agregar esos mismos parámetros al alcance {} funciona:

/*bindings: { modalInstance: ''<'', resolve: ''<'' },*/ scope: { modalInstance: ''<'', resolve: ''<'' },

* Descubrí después de escribir lo anterior que un parámetro de alcance adicional, foo, no estaba disponible en $ scope hasta que lo asigné desde $ scope.resolve. Así que tuve que hacer esto en $ scope.init (): $ scope.foo = $ scope.resolve.foo. No estoy seguro de por qué. Supongo que tiene que ver con el uso de mi UI Bootstrap Modal + Directives

Esto puede ser obvio para otros, pero no fue para mí ser relativamente nuevo en AnguluarJS.

Mi problema era usar Directivas con UI-Bootstrap Modals que son compatibles con Directivas pero diseñadas y documentadas para usar con Componentes.


Quizás no sea la mejor práctica, pero tiene un acceso más fácil a esos valores:

$scope.$ctrl.contactId

Puede obtener todos los enlaces en la propiedad $ ctrl dentro del $ scope.

Espero su ayuda


Sugeriré algunos cambios que realmente necesitaría para evitar estos errores inusuales.

app.component("test", { bindings: { "myContactId": "<" }, controller:function(){ var self=this; this.$onInit=function(){ // do all your initializations here. // create a local scope object for this component only. always update that scope with bindings. and use that in views also. self.myScopeObject=self.myContactId } }, template:''<p>{{$ctrl.myScopeObject}}</p>'' } <test my-contact-id="8"></test>

algunos puntos :

  1. pasar enlaces a un componente en html siempre va a estar en caso de kebab ex my-contact-id y su variable javascript respectiva estará en caso de cammal: myContactId.

  2. si está pasando el valor en lugar del objeto, use ''@'' en los enlaces. si está usando un objeto y pasa el objeto a bindigs, use ''<. si desea un enlace bidireccional a ese objeto, use ''='' en la configuración de enlaces

bindings:{ value:''@'', object:''<'', // also known as one-way twoWay:''='' }


Voy a agregar otra respuesta como seguimiento de @jusopi y la respuesta aceptada, solo para aquellos que puedan encontrar mi problema. Con respecto al componente, incluso después del $onInit , mis datos seguían siendo nulos, ya que el valor del servidor todavía no se recibía. Para contrarrestar esto (aunque puede haber una mejor manera de manejar esta situación), también aproveché el gancho $onChanges . $onChanges devolverá los datos que han cambiado cuando se pasan, y puede analizar esa información o simplemente llamar al enlace como this.contactId y se actualizará.

Se proporcionan más detalles en la documentation : https://docs.angularjs.org/guide/component