Синхронизируйте состояния нескольких экземпляров одного и того же компонента Ember.

Вот ситуация:

Я написал компонент facility-search, который ищет данные некоторых приборов. Я поместил несколько экземпляров {{facility-search}} в один и тот же шаблон (вкладки). Этот компонент имеет несколько полей ввода, где мы можем написать ключевые слова для поиска. Я хочу наблюдать за изменением значения поля ввода и обновлять его для другого экземпляра компонента, чтобы они оба были синхронизированы.

Это то, что я делаю в components/facility-search.js

import Ember from 'ember';
import Em from 'ember';

var FacilitySearchComponent = Ember.Component.extend({

  // Tag name appears in HTML
  tagName: 'div',

  // RandomNumber
  searchBoxId: null,

  // All Facilities
  allFacilities: null,

  // Search Values
  textFacility: "",
  textCountry: "",
  textSpecies: "",

  // Text Input Ids needed for <label for="id"/>
  // Elements in multuple components should not have same id
  textFacilityId: 'text-facility',
  textCountryId: 'text-country',
  textSpeciesId: 'text-species',

  // Initialize Ids
  randomNumber: function(){
    this.set('searchBoxId',(Math.floor(Math.random() * 100) + 1));
    this.set('textFacilityId', this.get('textFacilityId') + "-" + this.get('searchBoxId'));
    this.set('textCountryId', this.get('textCountryId') + "-" + this.get('searchBoxId'));
    this.set('textSpeciesId', this.get('textSpeciesId') + "-" + this.get('searchBoxId'));
  }.on('init'),

  // When component is inserted
  didInsertElement: function() {
    this.set('filteredFacilities', this.get('allFacilities'));
  },

  // Observe Search Values
  watchForFilterChanges: function() {
    this.filterResults();
  }.observes('textFacility', 'textCountry', 'textSpecies'),

  // Filter Data
  filterResults: function() {
    var facilities = // Some mechanism to filter data
    self.sendAction('updateFacilities', facilities);
  }.on('allFacilities'),

  actions: {
    clearSearch: function() {
      this.set('textFacility', null);
      this.set('textCountry', null);
      this.set('textSpecies', null);
      this.filterResults();
    },

  }
});

export default FacilitySearchComponent;

Это мой templates/components/facility-search.hbs

<div class="card">
  <div class="card-content directory-search">
    <div class="card-title grey-text text-darken-3">
      <h4>Search Facilities</h4>
      <h4><small class="teal-text">{{filteredFacilities.length}} total</small></h4>
    </div>
    <form {{action "textSearch" this on="submit" data="lol"}}>
      <div class="row">
        <div class="input-field col s12">
          <label for="{{textFacilityId}}">Search by facility</label>
          {{input value=textFacility type="text" id=textFacilityId label="Facility Name"}}
        </div>
        <div class="input-field col s12">
          <label for="{{textCountryId}}">Search by country</label>
          {{input value=textCountry type="text" id=textCountryId label="Facility Country"}}
        </div>
        <div class="input-field col s12">
          <label for="{{textSpeciesId}}">Search by species</label>
          {{input value=textSpecies type="text" id=textSpeciesId label="Facility Species"}}
        </div>
      </div>
    </form>
    <a {{action 'clearSearch'}} class="waves-effect waves-light btn"><i class="material-icons right">clear_all</i>clear search</a>
  </div>
</div>

Это мой controllers/map.js

import Ember from 'ember';
import pagedArray from 'ember-cli-pagination/computed/paged-array';

export default Ember.Controller.extend({

  // Facility to be shown in modal
  selectedFacility: null,

  // Facilities to be shown in search
  filteredFacilities: [],

  // Initialize filteredFacilities to model
  initializeFacilities: function() {
    this.set('filteredFacilities', this.get("model"));
  }.observes('model'),

  actions: {
    showFacilityInModal: function(facility){
      this.set('selectedFacility', facility);
    },
    updateFacilities: function(facilities){
      this.set('filteredFacilities', facilities);
    },
  }
});

Это routes/map.js

import Ember from 'ember';

export default Ember.Route.extend({
    model: function() {
        return this.store.find('facility');
    },
});

И вот как я использую компонент в templates/map.hbs

{{facility-search allFacilities=model updateFacilities='updateFacilities'}}

Я узнал, что если мы поместим компонент несколько раз; он будет иметь полные новые экземпляры. Поэтому обновление переменных textFacility и других нельзя наблюдать в другом экземпляре того же компонента. Но я хочу обновить эти значения и в другом экземпляре. Любая идея, как мы можем синхронизировать состояния нескольких экземпляров одного и того же компонента?


person Chaitanya Chandurkar    schedule 08.07.2015    source источник


Ответы (2)


Насколько я понимаю, вы спрашиваете, что хотите разделить значения между всеми компонентами, поэтому, если вы измените его в одном, он изменится в другом.

Ты можешь это сделать:

  text : {
    facility: "",
    country: "",
    species: "",
  }

вместо

  textFacility: "",
  textCountry: "",
  textSpecies: "",

Объявление его как объекта означает, что он будет общим для всех экземпляров компонента, как статическая переменная.

person jax    schedule 09.07.2015

Я нашел обходной путь!! Не уверен, что это правильный способ сделать это.

Я поместил переменные textCountry в controllers/map.js и передал их компоненту следующим образом:

{{facility-search textCountryComponentSpec=textCountry allFacilities=model updateFacilities='updateFacilities'}}

где textCountryComponentSpec содержит это значение в компоненте. Затем я наблюдал изменения в textCountryComponentSpec в компоненте и обновление textCountry в контроллере. Поскольку он передается компонентам, он отражает изменения.

Если вы знаете лучший способ, пожалуйста, напишите.

person Chaitanya Chandurkar    schedule 08.07.2015