angularjs - parametros - pasar datos entre componentes angular 6
¿Cómo pasar datos entre componentes hermanos sin usar $ scope? (3)
Enfoque componente
Le sugiero que se alinee con el enfoque de componente Angular 2 y use el enfoque de inputs / outputs . Si lo hace, podrá migrar fácilmente a Angular 2, porque los componentes serán conceptualmente idénticos (con una diferencia solo en la sintaxis). Así que aquí está la forma en que lo haces.
Básicamente, queremos que el encabezado y los componentes principales compartan el estado con el encabezado para poder cambiarlo.
Hay varios enfoques que podemos usar para que funcione, pero el más simple es usar la propiedad del controlador primario intermedio.
Así que supongamos que el controlador principal (o componente) define esta propiedad de
view
que desea que utilicen los componentes de encabezado (puede leer y modificar) y principal (puede leer).
Componente de encabezado : entrada y salida.
Así es como podría verse el componente de encabezado simple:
.component(''headerComponent'', {
template: `
<h3>Header component</h3>
<a ng-class="{''btn-primary'': $ctrl.view === ''list''}" ng-click="$ctrl.setView(''list'')">List</a>
<a ng-class="{''btn-primary'': $ctrl.view === ''table''}" ng-click="$ctrl.setView(''table'')">Table</a>
`,
controller: function() {
this.setView = function(view) {
this.view = view
this.onViewChange({$event: {view: view}})
}
},
bindings: {
view: ''<'',
onViewChange: ''&''
}
})
La parte más importante aquí son los enlaces.
Con
view: ''<''
especificamos que el componente de
header
podrá leer algo externo y vincularlo como propiedad de
view
del propio controlador.
Con
onViewChange: ''&''
salidas definidas por componentes
onViewChange: ''&''
: el canal para notificar / actualizar el mundo exterior con lo que necesite.
El componente de encabezado enviará algunos datos a través de este canal, pero no sabe qué hará el componente principal con él, y no debería importarle.
Por lo tanto, significa que el controlador de
header
se puede usar como
<header-component view="root.view" on-view-change="root.view = $event.view"></header-component>
Componente principal : entrada.
El componente principal es más simple, solo necesita definir la entrada que acepta:
.component(''mainComponent'', {
template: `
<h4>Main component</h4>
Main view: {{ $ctrl.view }}
`,
bindings: {
view: ''<''
}
})
Vista principal
Y finalmente todo se unió:
<header-component view="root.view" on-view-change="root.view = $event.view"></header-component>
<main-component view="root.view"></main-component>
Echa un vistazo y juega con una demostración simple.
angular.module(''demo'', [])
.controller(''RootController'', function() {
this.view = ''table''
})
.component(''headerComponent'', {
template: `
<h3>Header component</h3>
<a class="btn btn-default btn-sm" ng-class="{''btn-primary'': $ctrl.view === ''list''}" ng-click="$ctrl.setView(''list'')">List</a>
<a class="btn btn-default btn-sm" ng-class="{''btn-primary'': $ctrl.view === ''table''}" ng-click="$ctrl.setView(''table'')">Table</a>
`,
controller: function() {
this.setView = function(view) {
this.view = view
this.onViewChange({$event: {view: view}})
}
},
bindings: {
view: ''<'',
onViewChange: ''&''
}
})
.component(''mainComponent'', {
template: `
<h4>Main component</h4>
Main view: {{ $ctrl.view }}
`,
bindings: {
view: ''<''
}
})
<script src="https://code.angularjs.org/1.5.0/angular.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.css" />
<div class="container" ng-app="demo" ng-controller="RootController as root">
<pre>Root view: {{ root.view }}</pre>
<header-component view="root.view" on-view-change="root.view = $event.view"></header-component>
<main-component view="root.view"></main-component>
</div>
Demostración: http://plnkr.co/edit/ODuY5Mp9HhbqA31G4w3t?p=info
Aquí hay una publicación de blog que escribí que cubre el diseño basado en componentes en detalles: http://dfsq.info/site/read/angular-components-communication
Estoy haciendo un componente que contiene 3 componentes secundarios de esta manera:
<header-component>
<side-component>
<main-component>
El componente principal contiene una lista de héroes. El componente de encabezado contiene dos botones que se supone que cambian la vista del componente principal a la vista de lista o cuadrícula.
El problema que tengo ahora es pasar datos del componente de encabezado al componente principal. Entonces, cuando hago clic en el botón de cuadrícula, la vista del contenido principal debe cambiar a la vista de cuadrícula, lo mismo para la vista de fila.
¿Cómo se pueden pasar los datos entre los componentes secundarios en angular 1.5?
Aunque el enfoque del componente principal (transmitir datos a través de atributos) es una implementación perfecta, válida pero buena, podemos lograr lo mismo de una manera más simple utilizando una fábrica de la tienda .
Básicamente, la
Store
retiene los datos, a los que se hace referencia en el alcance de ambos componentes, lo que permite actualizaciones reactivas de la IU cuando cambia el estado.
Ejemplo:
angular
.module(''YourApp'')
// declare the "Store" or whatever name that make sense
// for you to call it (Model, State, etc.)
.factory(''Store'', () => {
// hold a local copy of the state, setting its defaults
const state = {
data: {
heroes: [],
viewType: ''grid''
}
};
// expose basic getter and setter methods
return {
get() {
return state.data;
},
set(data) {
Object.assign(state.data, data);
},
};
});
Luego, en sus componentes debería tener algo como:
angular
.module(''YourApp'')
.component(''headerComponent'', {
// inject the Store dependency
controller(Store) {
// get the store reference and bind it to the scope:
// now, every change made to the store data will
// automatically update your component UI
this.state = Store.get();
// ... your code
},
template: `
<div ng-show="$ctrl.state.viewType === ''grid''">...</div>
<div ng-show="$ctrl.state.viewType === ''row''">...</div>
...
`
})
.component(''mainComponent'', {
// same here, we need to inject the Store
controller(Store) {
// callback for the switch view button
this.switchViewType = (type) => {
// change the Store data:
// no need to notify or anything
Store.set({ viewType: type });
};
// ... your code
},
template: `
<button ng-click="$ctrl.switchViewType(''grid'')">Switch to grid</button>
<button ng-click="$ctrl.switchViewType(''row'')">Switch to row</button>
...
`
Si desea ver un ejemplo de trabajo, consulte este CodePen .
Al hacerlo, también puede habilitar la comunicación entre 2 o N componentes . Solo tienes que:
- inyectar la dependencia de la tienda
- asegúrese de vincular los datos de la tienda al alcance de su componente
como en el ejemplo anterior (
<header-component>
).
En el mundo real, una aplicación típica necesita administrar una gran cantidad de datos, por lo que tiene más sentido dividir lógicamente los dominios de datos de alguna manera.
Siguiendo el mismo enfoque
, puede agregar más fábricas de la Tienda
.
Por ejemplo, para administrar la información de usuario registrada actualmente más un recurso externo (es decir, catálogo), puede crear un
UserStore
más un
CatalogStore
; alternativamente,
UserModel
de
UserModel
y
UserModel
de
UserModel
;
esas entidades también serían buenos lugares para centralizar cosas como la comunicación con el back-end, agregar lógica empresarial personalizada, etc.
La gestión de datos será entonces responsabilidad exclusiva de las fábricas de la
Store
.
Tenga en cuenta que estamos mutando los datos de la tienda . Si bien este enfoque es simple y claro, podría no escalar bien porque producirá efectos secundarios . Si desea algo más avanzado (inmutabilidad, funciones puras, árbol de estado único, etc.), consulte Redux , o si finalmente desea cambiar a Angular 2, eche un vistazo a ngrx/store .
¡Espero que esto ayude! :)
No tiene que hacerlo de la manera Angular 2 porque en caso de que a veces migre ... Hágalo si tiene sentido que lo haga.
Use eventos personalizados para lograr esto.
puede pasar el mensaje a través de su aplicación utilizando despachadores de eventos
$emit(name, args); or $broadcast(name, args);
$emit(name, args); or $broadcast(name, args);
Y puede escuchar estos eventos usando el método $ on (nombre, oyente);
Espero eso ayude
Ref: https://docs.angularjs.org/api/ng/type/$rootScope.Scope#$emit
Ejemplo: puede notificar los cambios como a continuación desde su componente de encabezado
$rootScope.$emit("menu-changed", "list");
Y puede escuchar el cambio en su directiva de componente principal como
$rootScope.$on("menu-changed", function(evt, arg){
console.log(arg);
});