Acceder a la tienda desde el componente
Tengo un componente y cuando el usuario hace clic en el componente agrega algún valor para almacenar, intento usarlo de esta manera pero obtengo un error:
OlapApp.MeasureListItemComponent = Ember.Component.extend({
tagName: 'li',
isDisabled: false,
attributeBindings: ['isDisabled:disabled'],
classBindings: ['isDisabled:MeasureListItemDisabled'],
actions: {
add: function(measure) {
var store = this.get('store');
store.push('OlapApp.AxisModel', {
uniqueName: measure.uniqueName,
name: measure.name,
hierarchyUniqueName: measure.hierarchyUniqueName,
type: 'row',
isMeasure: true,
orderId: 1
});
}
}
});
Y esto es un error:
Uncaught TypeError: Cannot call method 'push' of undefined MeasureListItemComponent.js:18
¿Es posible enviar el registro al almacén desde el componente? ¿por qué no puedo acceder a la tienda ? mi nombre de modelo es 'AxisModel' y el espacio de nombres de la aplicación es 'OlapApp'
7 answers
En un component
la tienda no se inyecta automáticamente como en route
's o controller
's cuando se inicia su aplicación. Esto se debe a que se cree que los componentes están más aislados.
Lo que sigue a continuación no se considera una buena práctica. Un componente debe utilizar los datos pasados a él y no saber acerca de su entorno. La mejor manera de manejar este caso sería usar
sendAction
para burbujear lo que quieres hacer, y manejar la acción con elstore
en el controlador sí mismo.
@sly7_7 sugerencia es una buena, y si usted tiene una gran cantidad de componentes desde los que necesita acceso a la tienda, entonces podría ser una buena manera de hacerlo.
Otro enfoque para llegar a su store
podría ser conseguir la store
su component
que rodea controller
tiene referencia. En este caso no importa que controller
esto es porque cada controller
ya tiene una referencia a la store
inyectada en ella. Así que ahora para llegar a su store
podría hacerse obteniendo el component
's targetObject
que será el controller
que rodea el component
y luego obtener el store
.
Ejemplo:
OlapApp.MeasureListItemComponent = Ember.Component.extend({
...
actions: {
add: function(measure) {
var store = this.get('targetObject.store');
...
}
}
});
Ver aquí para un ejemplo de trabajo.
Espero que ayude.
Actualizar en respuesta a su comentario que tiene componentes anidados
Si, por ejemplo, su componente hijo solo está anidado en un nivel, aún podría referirse al objeto de destino del padre usando parentView
:
App.ChildCompComponent = Ember.Component.extend({
storeName: '',
didInsertElement: function() {
console.log(this.get('parentView.targetObject.store'));
this.set('storeName', this.get('parentView.targetObject.store'));
}
});
Actualizado ejemplo.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-05-27 06:21:33
Desde Ember v1.10, la tienda se puede inyectar a los componentes utilizando inicializadores, consulte: http://emberjs.com/blog/2015/02/07/ember-1-10-0-released.html#toc_injected-properties :
export default Ember.Component.extend({
store: Ember.inject.service()
});
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-03-21 08:45:46
La forma actual de ember-cli para hacer esto parece ser con un inicializador. Muy similar a la respuesta @Sly7_7.
Para obtener un modelo básico use:
ember g initializer component-store-injector
Entonces edita esto a:
// app/initializers/component-store-injector.js
export function initialize(container, application) {
application.inject('component', 'store', 'store:main');
}
export default {
name: 'component-store-injector',
initialize: initialize
};
Creo que esto agregará la tienda a todos los componentes.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-05-14 12:45:34
Desde Ember 2.1.0
export default Ember.Component.extend({
store: Ember.inject.service('store'),
});
Antes de Ember 2.1.0-forma de inyección de dependencia
App.MyComponent = Ember.Component.extend({
store: Ember.computed(function() {
return this.get('container').lookup('store:main');
})
});
Antes de Ember 2.1.0-controller way
Puede pasar store como propiedad del controlador:
App.MyComponent = Ember.Component.extend({
value: null,
store: null,
tagName: "input",
didInsertElement: function () {
if (!this.get('store')) {
throw 'MyComponent requires store for autocomplete feature. Inject as store=store'
}
}
});
Store está disponible en cada controlador. Así que en la vista padre puede incluir el componente de la siguiente manera:
{{view App.MyComponent
store=store
class="some-class"
elementId="some-id"
valueBinding="someValue"
}}
Pasar propiedades al componente se documenta aquí
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-03-25 06:36:52
No se si los componentes están destinados a ser utilizados de esta manera. Pero si quieres, creo que puedes declarar un inicializador e inyectar la tienda en todos los componentes.
Ember.onLoad('OlaApp', function(OlaApp) {
OlapApp.initializer({
name: 'injectStoreIntoComponents',
before: 'registerComponents',
initialize: function(container, application){
container.register('store:main', App.Store);
container.injection('component', 'store', 'store:main');
}
})
});
Aquí hay un ejemplo artificial pero funcional: http://jsbin.com/AlIyUDo/6/edit
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-11-17 09:44:29
La tienda se puede inyectar con la ayuda de la inyección de dependencia.
Ejemplo
import Ember from 'ember';
export default Ember.Component.extend({
/**
*
*/
store: Ember.inject.service(),
/**
* Initialize the component.
*/
init() {
this.initialize();
this._super();
},
/**
* Initialize the properties and prerequisites.
*/
initialize() {
// Set the component properties
this.todos().then((data) => {
this.set('todoEntries', data);
});
},
/**
* Returns the todo entries.
*
* @returns {*|Promise|Promise.<T>}
*/
todos() {
const store = this.get('store');
return store.findAll('todo');
},
});
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-05-23 16:25:19
Otra forma que nadie ha mencionado es simplemente pasar el controlador.almacenar en el componente, por ejemplo,
{{my-awesome-component store=controller.store}}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-11-03 07:47:00