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'

Author: MBehtemam, 2013-09-04

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 el store 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.

 42
Author: intuitivepixel,
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()
});
 42
Author: Jacob van Lingen,
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.

Robado de https://github.com/ember-cli/ember-cli-todos

 13
Author: jomofrodo,
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í

 13
Author: Jan Míšek,
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

 7
Author: sly7_7,
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');
  },

});
 5
Author: user634545,
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}}
 4
Author: TrevTheDev,
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