Ember 1.13, view lookup - javascript

Prior to ember 1.13 i was using
var containerView = Em.View.views[view_id];
to get the ContainerView instance with the view id and manually adding childViews to this container view, which used to work just fine.
As of ember 1.13 this view lookup is not supported. What is the recommended way of doing this?
The problem is there are multiple instances of the same containerView with different id's. So i need to get the right instance of containerView from lookup.
Thanks
Update:
I have a parent (widget) component:
parentComponent.hbs
.....
{{input value=someBinding1 click='showCalendar'}}
{{calendar-component month=month1 disableBefore=disableBefore1}}
{{input value=someBinding2 click='showCalendar'}}
{{calendar-component month=month2 disableBefore=disableBefore2}}
{{input value=someBinding3 click='showCalendar'}}
{{calendar-component month=month3 disableBefore=disableBefore3}}
.....
So essentially i can have multiple date(input) fields which when clicked should show up a calendar component. If i write the code as above it would create 3 (or as many date fields) instances of the calendar component. These number of date fields are dynamic. I did not wanted to create so many calendar components as i see sluggish performance on mobile devices.
So what i did was:
.....
{{input value=someBinding1 click='showCalendar'}}
{{calendar-container-view id='calendarContainerView1'}}
{{input value=someBinding2 click='showCalendar'}}
{{calendar-container-view id='calendarContainerView2'}}
{{input value=someBinding3 click='showCalendar'}}
{{calendar-container-view id='calendarContainerView2'}}
.....
And calendar-container-view had an empty childViews array to start.
When user clicks on input field i get the corresponding containerView instance using Em.View.views[containerViewId] and append the calendar instance to it.
When another input is clicked i remove it from old parent containerView and add it to the new container view.
So there is only one calendar instance created by parentComponent.js and removed and added to container view.
Hope it makes sense. I can create a jsbin if need be.
Thanks a lot!

I think you could operate your logic by model instances instead of views (I mean model concept here, it could be some array of objects or records array).
It's clear you have model (as some array), since you mentioned multiple instances.
You might do:
{{!-- list of input fields --}}
{{#each model as |item|}}
{{item-input-field item=item value=item.someBinding1 clickInput="setCurrentItemWhenInstanceClick"}}
{{/each}}
{{!-- and one calendar-component --}}
{{#if currentItem}}
{{calendar-component item=currentItem month=currentMonth disableBefore=currentDisableBefore}}
{{/if}}
where item-input-field is a component, that extends input and pass it's item up to parent component or controller through action clickInput (action up).
Then setCurrentItemWhenInstanceClick action in parent component (or controller) should set currentItem, currentMonth and currentDisableBefore data (data down to calendar-component), so your calendar-component will be shown.

Related

marionette control from backbone controls

I want to create mariontte control that consists of three backbone controls. First is Date Picker, second is numeric stepper and the third one is again Date Picker. The idea is that first date is the initial date and numeric stepper adds days and the result is shown in second Date Picker. Anyway I don't know how to create Marionette view when not all child items are the same. How should I approach this?
I think you can create a compositeview(or even layout can work) having three divs and render three different itemviews in the three divs by explicitly adding the el of the itemViews in the divs
e.g. if following is your compositeview template
<div id="first-datepicker"></div>
<div id="numeric-stepper"></div>
<div id="second-datepicker"></div>
Then in your compositeView JS you can render itemviews as follows
ui:{
firstDatepicker: "#first-datepicker",
numericStepper: "#numeric-stepper",
secondDatepicker: "#second-datepicker"
},
onRender: function(){
this.ui.firstDatepicker.html(new DatePickerView().render().el);
this.ui.numericStepper.html(new NumericStepperView().render().el);
this.ui.firstDatepicker.html(new DatePickerView().render().el);
}
But in case of layout you do not need to explicitly render the view, you can simply use show method of layout as
regions:{
firstDatepickerRegion: "#first-datepicker",
numericStepperRegion: "#numeric-stepper",
secondDatepickerRegion: "#second-datepicker"
},
onRender: function(){
this.firstDatepickerRegion.show(new DatePickerView());
this.numericStepperRegion.show(new NumericStepperView());
this.secondDatepickerRegion.show(new DatePickerView());
}

Angular Material md-chips not refreshing correctly

I am developing an app that works with a "Widget layout".
The user gets a page which is a Dashboard with different widgets he can interact with, such as a table, graphs etc.
I am adding a global "filter" using <md-chips>, the objective of this is having filters that are shared by all the widgets and can be updated by all the widgets.
My Filter list uses <md-chips>, with read-only and md-removable set to True. So filters can only be deleted, or added by interacting with the widgets (so only added programmatically).
One of the feature of this "module" is to add a new filter on a field when a Graph element is clicked.
Example :
Here is my Filters list before clicking a Graph element
Now I click on a Graph element which is in a Child controller of my Filter controller, it will $emit an event to say to the global controller : "I want to update the filters ! here is the filter to add"
And the Filter Controller will get that event and update his filters accordingly ($scope.tags is the list of filters and the model used in <md-chips>)
// CHIPS
$scope.tags = [];
$scope.readOnly = true;
$scope.removable = true;
// FILTER LISTENER
$scope.$on('filterChildChanged', function (event, filter) {
$scope.tags.push(filter);
console.log($scope.tags);
console.log("Parent event fired !");
});
At that point I would expect the <md-chips>element to refresh, because $scope.tags just got a new filter :
<md-chips
ng-model="tags"
readonly="readOnly"
md-removable="removable"
id="filters">
<md-chip-template>{{$chip.value}}</md-chip-template>
</md-chips>
But instead, nothing happens! and the weird part is, it refreshes when I click on one of the existing chip (I had a "test" chip) !
TESTS :
So when I push a test chip on the array before rendering :
$scope.tags.push({field: "testField", value: "test"});
And click on a bunch of Graph elements, $scope.tags is perfectly updated, BUT the visual stays the same until I select the chip "test", then all the <md-chips> appear just like it triggered some refresh function.
Any hint on why the <md-chips> element is not refreshed as $scope.tags (its model) is updated BUT is updated when a chip is selected ?
I tried to trigger md-on-select to force this behavior to happen every time I add a new filter to $scope.tags but I got no luck so far !
Thanks for reading !
NOTE : I am using the latest version of Angular MATERIAL (HEAD MASTER) see doc here : https://material.angularjs.org/HEAD/ | built from the GitHub repository.
EDIT : The problem comes from $$hashKey not being added to the objects, they are only added when I click on one of the existing tags, I need to find a way to add this $$hashKey attribute when I add a new filter
The problem came from the absence of $$hashKey when I added a new filter to my filters model for my chips ($scope.tags).
So I just needed to change
$scope.tags.push(filter);
to
$scope.$apply(function () {
$scope.tags.push(filter);
});
And here is my console.log test
Good thing I learned :
the <md-chips> directive only knows it needs to be updated if its <chip> objects have a $$hashKey
See this on scope.$apply

Emberjs loading dynamic subview

I'm just getting started with emberjs and I have some problems understanding how to dynamically change views within a view.
I want to have a page with a calendar.
This page has some buttons on the top to switch between different calendar views (day, week, month) and some filter options for the appointments within this view.
See this mockup:
Currently I have created a calendar route and a CalendarIndexView and template.
This template will contain the basic filter and view toggle buttons.
Within the index view I can call another view to display the grid.
<div class="calendar-container">
{{view monthView}}
</div>
The collection/context that is attached to these different views should not change because the filter is also applied on this.
The problem I have is that I don't know how to change the monthView to for example dayView after the "day" button is clicked.
Should I handle this in a router, controller or in the main calendar view?
If not view the router, how would make this view switching dynamic?
One of the core strengths of Ember is the router - everything is driven by the URL. I don't think you should part from that.
Use different routes for the different views within a calendar resource (in the router):
this.resource('calendar', { path: '/calendar' }, function() {
this.route('day');
this.route('week');
this.route('month');
});
Set the model on the calendar resource
In the nested routes (day, week (you could make month the default by using the calendar index route for it)), use the same model as in the calendar route, just filter it down to what you want. e.g.:
export default Ember.Route.extend({
model: function() {
return this.modelFor('calendar').filter(function(event) { ... });
}
});
For the people filter create a computed property in the controller that filters the events on the model and use that in the templates instead of the actual model. In that, if a person is selected, you can filter out any events without that person.
selectedPerson: null, // bind that e.g. to a select with all the people or change that with an action
filteredEvents: function() {
if (! this.get('selectedPerson')) {
return this.get('events');
}
return this.get('events').filterBy('attendee', this.get('selectedPerson'));
}.property('events.#each.attendee', 'selectedPerson')
Better than (4.): Do the filtering via query parameters. That way, you could be very flexible and even build powerful text search pretty easily...
Hope that helps and happy to see different approaches...

Ember Select populated by other Ember Select not updating selection binding

I'm new to Ember.js and I'm trying to figure out how Select views bind their selection to the controller. I have this template:
{{view Ember.Select
contentBinding="content"
selectionBinding="selectedCompany"
optionLabelPath="content.name"}}
{{view Ember.Select
contentBinding="selectedCompany.employees"
selectionBinding="selectedEmployee"
optionLabelPath="content.name"}}
Employee: {{selectedEmployee.name}}
Age: {{selectedEmployee.age}}
I find that the second select does update when selectedCompany changes, but I can't reference the values of name or age in selectedEmployee until I change the second select's value to a different value physically.
How do I make it so that the selectedEmployee is set when the first select changes, such that I can use it's value?
For better clarity, I have my working code here.
Changing content of second selectbox does not actualy change its selection. You have to do it manually, for example by adding following method to controller
onChangeCompany : function() {
if (!this.get('selectedCompany.employees').contains(this.get('selectedEmployee'))) {
this.set('selectedEmployee', this.get('selectedCompany.employees').objectAt(0));
}
}.observes('selectedCompany')
It stil needs some non-null and array-range checking, but does the job - if you select an employee and then change company, employee will change as well.

Multiple selects instead of multi select in Ember application

in Ember multiselects can be created using the multiple property of the Ember.Select view (e.g. in this post).
What I want to do is substituting a multiselect with multiple "normal" selects, which are all bound to the same array. Let's say I have two single selects, then both should be bound to an array fooArray. When I select foo in the first select and bar in the second one, then fooArray should be ['foo', 'bar'].
Any ideas on how to do that?
Kind regards,
Marius
You can set a selectionBinding for each select and a computed property taha makes the array... sure there are better ways to do this... it depends of the number of selects you deal with, because, in this example, the returned array is recalculated each time you get it
and this don't scale very well
App.SelectionController = Ember.ObjectController.extend({
select1Value:null,
select2Value:null,
select3Value:null,
selectedArray:function{
return Ember.Array(this.get('select1Value'),this.get('select2Value'),this.get('select2Value'));
}.property('select1Value','select2Value','select3Value')
});
In the view
{{view Ember.Select
contentBinding="YourSelectContent"
selectionBinding="App.SelectionController.select1Value"
[...]
{{view Ember.Select
contentBinding="YourSelectContent"
selectionBinding="App.SelectionController.select2Value"
[...]
{{view Ember.Select
contentBinding="YourSelectContent"
selectionBinding="App.SelectionController.select3Value"
[...]

Categories

Resources