Tengo un controlador responsable de comunicarme con una API para actualizar las propiedades de un usuario, nombre, correo electrónico, etc. Cada usuario tiene uno 'id'
que se pasa del servidor cuando se visualiza la página de perfil.
Me gustaría pasar este valor al controlador AngularJS para que sepa cuál es el punto de entrada de API para el usuario actual. He intentado pasar el valor ng-controller
. Por ejemplo:
function UserCtrl(id, $scope, $filter) {
$scope.connection = $resource('api.com/user/' + id)
y en el HTML
<body ng-controller="UserCtrl({% id %})">
donde {% id %}
imprime el id enviado desde el servidor. pero me salen errores
¿Cuál es la forma correcta de pasar un valor a un controlador en su creación?
javascript
angularjs
nickponline
fuente
fuente
Respuestas:
Notas:
Esta respuesta es vieja. Esto es solo una prueba de concepto sobre cómo se puede lograr el resultado deseado. Sin embargo, puede que no sea la mejor solución según algunos comentarios a continuación. No tengo ninguna documentación para respaldar o rechazar el siguiente enfoque. Consulte algunos de los comentarios a continuación para obtener más información sobre este tema.
Respuesta original
Respondí esto a Sí, absolutamente puedes hacerlo usando
ng-init
una simple función de inicio.Aquí está el ejemplo de ello en plunker
HTML
JavaScript
fuente
The only appropriate use of ngInit for aliasing special properties of ngRepeat, as seen in the demo below. Besides this case, you should use controllers rather than ngInit to initialize values on a scope.
ng-init
ocurra, consulte plnkr.co/edit / donCm6FRBSX9oENXh9WJ? p = vista previaLlegué muy tarde a esto y no tengo idea si es una buena idea, pero puede incluir el
$attrs
inyectable en la función del controlador, lo que permite que el controlador se inicialice utilizando los "argumentos" proporcionados en un elemento, por ejemploNuevamente, no tengo idea si es una buena idea, pero parece funcionar y es otra alternativa.
fuente
ng-init
: si está intentando vincular a un valor de alcance, ya está ejecutando la función del controlador antes de queng-init
ocurra; consulte plnkr.co/edit/donCm6FRBSX9oENXh9WJ?p=previewEsto tambien funciona.
Javascript:
HTML:
fuente
La vista no debe dictar la configuración
En Angular, la plantilla nunca debe dictar la configuración, que es inherentemente lo que las personas desean cuando quieren pasar argumentos a los controladores desde un archivo de plantilla. Esto se convierte en una pendiente resbaladiza. Si los ajustes de configuración están codificados en plantillas (por ejemplo, por una directiva o un atributo de argumento del controlador), ya no puede reutilizar esa plantilla para nada más que ese único uso. Pronto querrás volver a usar esa plantilla, pero con una configuración diferente y ahora para hacerlo, estarás preprocesando las plantillas para inyectar variables antes de que pase a angular o usando directivas masivas para escupir gigantes bloques de HTML para que pueda reutilizar todo el HTML del controlador, excepto el contenedor wrap div y sus argumentos. Para proyectos pequeños no es gran cosa. Para algo grande (en lo que sobresale angular), se pone feo rápidamente.
La alternativa: módulos
Este tipo de configuración es lo que los módulos fueron diseñados para manejar. En muchos tutoriales angulares, las personas tienen un solo módulo para toda su aplicación, pero realmente el sistema está diseñado y es totalmente compatible con muchos módulos pequeños, cada uno de los cuales envuelve piezas pequeñas de la aplicación total. Idealmente, los controladores, módulos, etc. se declararían en archivos separados y se unirían en fragmentos específicos reutilizables. Cuando su aplicación está diseñada de esta manera, obtiene una gran cantidad de reutilización además de argumentos fáciles de controlador.
El siguiente ejemplo tiene 2 módulos, reutilizando el mismo controlador, pero cada uno con su propia configuración. Esa configuración se pasa mediante inyección de dependencia mediante
module.value
. Esto se adhiere a la forma angular porque tenemos lo siguiente: inyección de dependencia del constructor, código de controlador reutilizable, plantillas de controlador reutilizables (el div del controlador podría incluirse fácilmente con ng-include), sistema fácilmente comprobable por unidad sin HTML y, por último, reutilizable módulos como el vehículo para unir las piezas.Aquí hay un ejemplo:
Véalo en acción: jsFiddle .
fuente
Al igual que @akonsu y Nigel Findlater sugieren, se puede leer la URL donde URL es
index.html#/user/:id
con$routeParams.id
y utilizarlo dentro del controlador.tu aplicación:
el servicio de recursos
el controlador
entonces,
elm
es accesible en la vista dependiendo deid
.fuente
Si
ng-init
no es para pasar objetos$scope
, siempre puede escribir su propia directiva. Entonces, esto es lo que obtuve:http://jsfiddle.net/goliney/89bLj/
Javasript:
HTML:
Pero mi enfoque solo puede modificar objetos, que ya están definidos en el controlador.
fuente
Parece que la mejor solución para usted es en realidad una directiva. Esto le permite seguir teniendo su controlador, pero definir propiedades personalizadas para él.
Use esto si necesita acceso a variables en el ámbito de ajuste:
Use esto si no necesita acceso a variables en el ámbito de ajuste:
fuente
Encontré variables de paso de $ routeProvider útiles.
Por ejemplo, utiliza un controlador MyController para múltiples pantallas, pasando algunas variables muy importantes "mySuperConstant" dentro.
Usa esa estructura simple:
fuente
Puede hacerlo al configurar las rutas para, por ejemplo,
Y luego úsalo como
Entonces, cuando configuramos la ruta que enviamos: itemType y la recuperamos más tarde de $ routeParams.
fuente
Hay otra forma de pasar parámetros a un controlador inyectando $ routeParams en su controlador y luego usando los parámetros de URL descritos aquí ¿Cuál es la forma más concisa de leer los parámetros de consulta en AngularJS?
fuente
Esta pregunta es antigua, pero luché durante mucho tiempo tratando de obtener una respuesta a este problema que funcionara para mis necesidades y no la encontré fácilmente. Creo que mi siguiente solución es mucho mejor que la actualmente aceptada, quizás porque angular ha agregado funcionalidad desde que esta pregunta se planteó originalmente.
Respuesta corta, el uso del método Module.value le permite pasar datos a un constructor de controladores.
Mira mi saqueador aquí
Creo un objeto modelo, luego lo asocio con el controlador del módulo, haciendo referencia al nombre 'modelo'
HTML / JS
El constructor en mi controlador acepta un parámetro con ese mismo identificador 'modelo' al que luego puede acceder.
Controlador
Notas:
Estoy usando la inicialización manual de bootstrapping , que me permite inicializar mi modelo antes de enviarlo a angular. Esto funciona mucho mejor con el código existente, ya que puede esperar para configurar sus datos relevantes y solo compilar el subconjunto angular de su aplicación cuando lo desee.
En el plunker, agregué un botón para alertar los valores del objeto modelo que se definió inicialmente en JavaScript y se pasó a angular, solo para confirmar que angular realmente hace referencia al objeto modelo, en lugar de copiarlo y trabajar con una copia.
En esta línea:
Estoy pasando el objeto MyController a la función Module.controller, en lugar de declarar como una función en línea. Creo que esto nos permite definir mucho más claramente nuestro objeto controlador, pero la documentación angular tiende a hacerlo en línea, así que pensé que debería aclararse.
Estoy usando la sintaxis "controlador como" y asignando valores a la propiedad "this" de MyController, en lugar de usar la variable "$ scope". Creo que esto también funcionaría bien usando $ scope, la asignación del controlador se vería así:
y el constructor del controlador tendría una firma como esta:
Si por alguna razón quisiera, también podría adjuntar este modelo como un valor de un segundo módulo, que luego adjuntará como una dependencia a su módulo primario.
Creo que su solución es mucho mejor que la actualmente aceptada porque
La forma en que Angular parece funcionar en la mayoría de los otros ejemplos que he visto hace que el controlador defina los datos del modelo, lo que nunca tuvo sentido para mí, no hay separación entre el modelo y el controlador, eso realmente no parece MVC para mi. Esta solución le permite realmente tener un objeto modelo completamente separado que pasa al controlador. Además, si utiliza la directiva ng-include, puede colocar todos sus html angulares en un archivo separado, separando completamente la vista del modelo y el controlador en piezas modulares separadas.
fuente
Si usa el enrutador angular-ui, entonces esta es la solución correcta: https://github.com/angular-ui/ui-router/wiki#resolve
Básicamente, declara un conjunto de dependencias para "resolver" antes de instanciar el controlador. Puede declarar dependencias para cada uno de sus "estados". Estas dependencias se pasan luego en el "constructor" del controlador.
fuente
Una forma de hacerlo sería tener un servicio separado que se pueda usar como un 'recipiente' para aquellos argumentos en los que son miembros de datos públicos.
fuente
Realmente no me gustó ninguna de las soluciones aquí para mi caso de uso particular, así que pensé que publicaría lo que hice porque no lo vi aquí.
Simplemente quería usar un controlador más como una directiva, dentro de un ciclo ng-repeat:
Ahora, para acceder a la
objParameter
creación en cada DirectivaLikeController (o para obtener el objParameter actualizado en CUALQUIER momento), todo lo que necesito hacer es inyectar $ scope y llamar$scope.$eval('objParameter')
:El único inconveniente real que veo es que requiere que el controlador principal sepa que se nombra el parámetro
objParameter
.fuente
No, no es posible. Creo que puedes usar ng-init como hack http://docs.angularjs.org/api/ng.directive:ngInit .
fuente
ng-init
ocurra, consulte plnkr.co/edit / donCm6FRBSX9oENXh9WJ? p = vista previaAquí hay una solución (basada en la sugerencia de Marcin Wyszynski) que funciona donde desea pasar un valor a su controlador pero no está declarando explícitamente el controlador en su html (que ng-init parece requerir), si, por ejemplo, está renderizando sus plantillas con ng-view y declarando cada controlador para la ruta correspondiente a través de routeProvider.
JS
html
En esta solución, CurrentUser es un servicio que se puede inyectar en cualquier controlador, con la propiedad .name disponible.
Dos notas:
Un problema que he encontrado es que .name se configura después de que se carga el controlador, por lo que como solución temporal tengo un breve tiempo de espera antes de mostrar el nombre de usuario en el alcance del controlador. ¿Hay alguna forma ordenada de esperar hasta que .name se haya configurado en el servicio?
Esto se siente como una manera muy fácil de obtener un usuario actual en su aplicación Angular con toda la autenticación mantenida fuera de Angular. Podría tener un before_filter para evitar que los usuarios no registrados accedan al html en el que su aplicación Angular está iniciada, y dentro de ese html simplemente podría interpolar el nombre del usuario conectado e incluso su ID si desea interactuar con los detalles del usuario a través de solicitudes http desde su aplicación Angular. Puede permitir que los usuarios no registrados utilicen la aplicación Angular con un 'usuario invitado' predeterminado. Cualquier consejo sobre por qué este enfoque sería malo sería bienvenido, ¡es demasiado fácil ser sensible!)
fuente
Esta es una expansión de la excelente respuesta de @Michael Tiller . Su respuesta funciona para inicializar variables desde la vista inyectando el
$attrs
objeto en el controlador. El problema se produce si se llama al mismo controlador$routeProvider
cuando se navega por enrutamiento. Entonces se produce un error en el inyectorUnknown provider : $attrsProvider
porque$attrs
solo está disponible para inyección cuando se compila la vista. La solución es pasar la variable (foo)$routeParams
al inicializar el controlador desde la ruta y$attrs
al inicializar el controlador desde la vista. Aquí está mi solución.De la ruta
Esto maneja una URL como
'/mypage/bar'
. Como puede ver, foo se pasa por url param y proporcionamos$injector
un objeto en blanco para$attrs
que no haya errores en el inyector.De la vista
Ahora el controlador
fuente