Here's the situation:
I wrote a component facility-search
which searches through some fixture data. I put multiple instances of {{facility-search}}
on same template (Tab Pages). This component has some input boxes where we can write search keywords. I want to observe change in value of input box and update the same to another instance of component so that both of them will be in sync.
This is what I'm doing in 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;
This is my 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>
This is my 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);
},
}
});
This is routes/map.js
import Ember from 'ember';
export default Ember.Route.extend({
model: function() {
return this.store.find('facility');
},
});
And this is how I'm using component in templates/map.hbs
{{facility-search allFacilities=model updateFacilities='updateFacilities'}}
I learned that if we put component multiple times; it will have complete new instances. So updating variables textFacility
and others cannot be observed in another instance of same component. But I want to update those values in another instance as well. Any idea how we can sync the states of multiple instances of same component?
If I understand you question you want to share values between all component so if you change it in one, it changes in the other.
You can do this:
text : {
facility: "",
country: "",
species: "",
}
instead of
textFacility: "",
textCountry: "",
textSpecies: "",
Declaring it as an object means it will be shares across all component instances like a static variable.