j'ai un composant et lorsque l'utilisateur clique sur le composant, il ajoute une valeur à stocker, j'essaie d'utiliser de cette façon mais j'obtiens une erreur:
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
});
}
}
});
et c'est une erreur:
Uncaught TypeError: Cannot call method 'Push' of undefined MeasureListItemComponent.js:18
est-il possible de pousser l'enregistrement pour le stocker à partir du composant? pourquoi je ne peux pas accéder au magasin? mon nom de modèle est "AxisModel" et l'espace de noms de l'application est "OlapApp"
Dans un component
le magasin n'est pas injecté automatiquement comme dans les route
ou controller
au démarrage de votre application. En effet, les composants sont considérés comme plus isolés.
Ce qui suit ci-dessous n'est pas considéré comme une meilleure pratique. Un composant doit utiliser les données qui lui sont transmises et ne pas connaître son environnement. La meilleure façon de gérer ce cas serait d'utiliser
sendAction
pour développer ce que vous voulez faire et de gérer l'action avecstore
dans le contrôleur lui-même.
@ sly7_7 est une bonne suggestion, et si vous avez beaucoup de composants d'où vous avez besoin d'accéder au magasin, alors ce pourrait être un bon moyen de le faire.
Une autre approche pour accéder à votre store
pourrait être d'obtenir la référence de store
à votre component
entourant controller
. Dans ce cas, peu importe quel controller
c'est parce que chaque controller
a déjà une référence au store
injecté dedans. Alors maintenant, pour arriver à votre store
pourrait être fait en obtenant le component
's targetObject
qui sera le controller
entourant le component
puis récupérez le store
.
OlapApp.MeasureListItemComponent = Ember.Component.extend({
...
actions: {
add: function(measure) {
var store = this.get('targetObject.store');
...
}
}
});
Voir ici pour un exemple de travail.
J'espère que ça aide.
Si, par exemple, votre composant enfant n'est imbriqué que d'un niveau, vous pouvez toujours vous référer à targetObject du parent en utilisant parentView
:
App.ChildCompComponent = Ember.Component.extend({
storeName: '',
didInsertElement: function() {
console.log(this.get('parentView.targetObject.store'));
this.set('storeName', this.get('parentView.targetObject.store'));
}
});
Mise à jour exemple .
Depuis Ember v1.10, le magasin peut être injecté aux composants à l'aide d'initialiseurs, voir: http://emberjs.com/blog/2015/02/07/ember-1 -10-0-release.html # toc_injected-properties :
export default Ember.Component.extend({
store: Ember.inject.service()
});
Depuis Ember 2.1.0
export default Ember.Component.extend({
store: Ember.inject.service('store'),
});
avant Ember 2.1.0 - voie d'injection de dépendance
App.MyComponent = Ember.Component.extend({
store: Ember.computed(function() {
return this.get('container').lookup('store:main');
})
});
avant Ember 2.1.0 - chemin du contrôleur
Vous pouvez transmettre le magasin en tant que propriété à partir du contrôleur:
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'
}
}
});
Le magasin est disponible sur chaque contrôleur. Ainsi, dans la vue parent, vous pouvez inclure le composant comme suit:
{{view App.MyComponent
store=store
class="some-class"
elementId="some-id"
valueBinding="someValue"
}}
La transmission des propriétés au composant est documentée ici
La façon actuelle de faire cela avec ember-cli semble être avec un initialiseur. Très similaire à la réponse @ Sly7_7.
Pour obtenir un modèle de base, utilisez:
ember g initializer component-store-injector
Modifiez ensuite ceci pour:
// 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
};
Je crois que cela ajoutera le magasin à tous les composants.
Je ne sais pas si les composants sont destinés à être utilisés de cette façon. Mais si vous le souhaitez, je pense que vous pouvez déclarer un initialiseur et injecter le magasin dans tous les composants.
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');
}
})
});
Voici un exemple artificiel mais fonctionnel: http://jsbin.com/AlIyUDo/6/edit
Le magasin peut être injecté à l'aide d'une injection de dépendance.
Exemple
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');
},
});
Une autre façon que personne n'a encore mentionnée est de simplement passer controller.store au composant, par ex.
{{my-awesome-component store=controller.store}}