Date range picker in Ember.view - ember.js

I'm trying implement Date range picker to ember view.
App.DaterangepickerView = Ember.View.extend({
tagName: "input",
attributeBindings: ["start", "end"],
start: null,
end: null,
didInsertElement: function() {
var self = this;
this.$().daterangepicker(
{
format: 'YYYY-MM-DD',
startDate: '2013-01-01',
endDate: '2013-12-31'
},
function(start, end) {
console.log("Date-range-picker:");
self.set('startdate',start.format('DD-MM-YYYY'));
self.set('end',end.format('DD-MM-YYYY'));
console.log("start: " + self.get('start'));
console.log("end: " + self.get('end'));
}
)
},
});
template:
<script type="text/x-handlebars" data-template-name="daterangepicker">
{{view App.DaterangepickerView startBinding="start" endBinding="end"}}
start date: {{start}}
end date: {{end}}
</script>
controller:
App.DatatableController = Ember.ArrayController.extend({
start: "2013-08-07",
end: "2013-08-09",
});
startBinding and endBinding are probably wrong parameters of ember.view, but I don't know how to correctly write by contentBinding. Picker is shows and set a correct information to console, but I need set controller from there. Did you do something similar?

You need to use start intead of startdate.
Update this code from:
self.set('start',start.format('DD-MM-YYYY'));
To
self.set('startdate',start.format('DD-MM-YYYY'));
so your start binding will work.
It's a good idea to pass the current start and end dates to daterangepicker, so when you show the picker it will have the selected value:
this.$().daterangepicker(
{
startDate: this.get('start'),
endDate: this.get('end')
}
The final result is the following:
App.DaterangepickerView = Ember.View.extend({
tagName: "input",
attributeBindings: ["start", "end"],
start: null,
end: null,
format: 'YYYY-MM-DD',
didInsertElement: function() {
var self = this;
var format = this.get('format');
this.$().daterangepicker(
{
format: format,
startDate: this.get('start'),
endDate: this.get('end')
},
function(start, end) {
self.set('start',start.format(format));
self.set('end',end.format(format));
}
)
},
});
And this is a sample fiddle with this working http://jsfiddle.net/marciojunior/UTV3U/
I hope it helps

Related

Ember: use controller data in route or how to fetch data properly

This question is a follow up on my previous question: Architecture for reusable object in ember
In my app I create multiple charts using an Ember.Component. The daterange for all the charts is controlled by a Daterangepicker which has its own controller etc.. Now the data for each chart is fetched in the IndexRoute (with an ajax call), and the daterange is passed in the query string.
The problem is that I can't seem to figure out how to access the daterange from the IndexRoute. Here's my code:
IndexRoute.js
App.IndexRoute = Ember.Route.extend({
model: function(){
var that = this;
return Ember.Object.extend({
registrationsData: null,
registrations: function() {
var self = this;
$.ajax({
url: Routing.generate('ysu_user_api_statistics_registrations', {startDate: that.dateRange.startDate, endDate: that.dateRange.endDate}),
success: function(data) {
var labels = [];
var values = [];
var chartData = {
labels : data.labels,
datasets : [
{
data : data.values,
}
],
};
self.set('registrationsData', chartData);
}
});
}.property(),
}).create();
},
dateRange: Ember.Object.create({
id: 1,
startDate: '2013-08-01',
endDate: '2013-08-31'
}),
});
Index.hbs
{{ my-chart title="Registrations" dataBinding=model.registrations registrationsDataBinding=model.registrationsData}}
MyChartComponent.js
App.MyChartComponent = Ember.Component.extend({
...
dataBinding: null,
registrationsDataBinding: null,
dateRangeBinding: null,
modelDateRangeBinding: null,
chartContext: null,
myChartController: null,
didInsertElement: function() {
/* Create and set controller */
if (!this.get('myChartController')) {
myChartController = new App.MyChartController()
this.set('myChartController', myChartController);
}
this.set('chartContext', $(this.get('element')).find('canvas')[0].getContext("2d"));
},
drawChart: function() {
if(this.get('chartContext')) {
var ctx = this.get('chartContext');
var options = {
bezierCurve : false,
pointDotRadius : 6,
pointDotStrokeWidth : 4,
datasetStrokeWidth : 4,
}
var myNewChart = new Chart(ctx).Line(this.get('registrationsDataBinding'), options);
}
}.observes('registrationsDataBinding', 'myChartController.dateRange'),
});
MyChartController.js
App.MyChartController = Ember.ArrayController.extend({
container: App.__container__,
needs: ['daterangepicker'],
dateRange: 'controllers.daterangepicker.selectedRange',
dateRangeBinding: 'controllers.daterangepicker.selectedRange',
});
I must admit, this setup feels kinda weird. So ultimately my question is:
What would be the correct way to fetch data for my charts based on startDate and endDate set in my DatePickerController?
I have been struggling with this problem as well.
In some of my apps, I've needed the URL to control the date range (e.g. a particular month). In these cases, I would created a MonthRoute and a MonthModel - think of it as a monthly report. The MonthModel has a hasMany property of the actual data I wanted to chart:
App.Month = DS.Model.extend({
companies: DS.hasMany('App.Company')
});
A datepicker would let the user enter a new route, which would fetch (say) the Jan-2013 month model
{
month: {
id: 'Jan-2013',
companies: [
{name: 'Acme, Inc', revenue: 10425, ...},
...
]
}
}
Then, I would set the embedded companies data on my CompaniesController in the setupController hook:
App.MonthRoute = Ember.Route.extend({
setupController: function(controller, model) {
controller.set('model', model);
this.controllerFor('companies').set('model', model.get('companies'));
}
});
Then, I would do the various array manipulations on my CompaniesController, and make that data available to my charts.
I have some code for this up on github, as well as a demo. I'd be interested to hear your thoughts.

Update an ember.js view when content is dropped

I'm trying to implement drag and drop with Ember.js. I have everything working except getting the view to update at the end. Here's a jsfiddle:
http://jsfiddle.net/rsaNy/
If you drag something from the source list and drop it in the dest div, I want it to be added to the display. The two alerts that I have set up confirm that the data structures are actually being updated, but the update is not being reflected in the view. How do I solve this? Here's the code.
DragNDrop = Ember.Namespace.create();
DragNDrop.cancel = function(event) {
event.preventDefault();
return false;
};
App = Ember.Application.create();
testItems =
[ { name: "Alpha" } ,
{ name: "Bravo" } ,
{ name: "Charlie" } ];
App.SourceItemView = Ember.View.extend({
templateName: 'sourceItem',
tagName: 'li',
attributeBindings: 'draggable',
draggable: 'true',
dragStart: function(event) {
var dataTransfer = event.originalEvent.dataTransfer;
var msg = this.get('content');
dataTransfer.setData('text', JSON.stringify(msg));
}
});
App.SourceView = Ember.View.extend({
templateName: 'source',
tagName: 'div',
classNames: ['well']
});
App.DestView = Ember.View.extend({
templateName: 'dest',
tagName: 'div',
classNames: ['well'],
dragEnter: DragNDrop.cancel,
dragLeave: DragNDrop.cancel,
dragOver: DragNDrop.cancel,
drop: function(event) {
var c = this.get('content');
var fieldStr = event.originalEvent.dataTransfer.getData('text');
alert(fieldStr);
c.push(JSON.parse(fieldStr));
var str = '';
for (var i = 0; i < c.length; i++) {
str += c[i].name+' ';
}
alert(str);
return true;
}
});
App.IndexController = Ember.ObjectController.extend({
content: { source: testItems,
dest: [{name: "Delta"}] }
});
You need to use the Ember Array pushObject() method instead of push(). This allows Ember to keep track of the data changes for it's binding system, which is how the view knows to update itself. It is the same idea of having to use get() and set() all the time.
drop: function(event) {
var c = this.get('content');
var fieldStr = event.originalEvent.dataTransfer.getData('text');
alert(fieldStr);
c.pushObject(JSON.parse(fieldStr));
//...
Here is the working JSFiddle

Two Ember.JS ArrayControllers?

I'm having a bit of a problem with an Ember.JS app I'm building:
App.userController = Ember.ArrayController.create({
content: [],
init: function() {
this.set('content', []);
this.refresh();
},
refresh: function() {
//Refresh Action
}
});
App.supplierController = Ember.ArrayController.create({
content: [],
init: function() {
this.set('content', []);
this.refresh();
},
refresh: function() {
//Refresh Action
}
});
<h1>Users</h1>
{{#each user in App.userController}}
{{user.name}} - {{user.age}}
{{/each}}
<h1>Suppliers</h1>
{{#each supplier in App.supplierController}}
{{supplier.name}} - {{supplier.revenue}}
{{/each}}
It works... but the users are displayed in the same list as the suppliers? If I remove the supplier controller, they display in the correct position. I think this is to do with having two instances of Ember.ArrayController but I'm not sure. It displays like this:
Users
-----------
Suppliers
-----------
User 1 -
User 2 -
Supplier 1 - £100
When it should be displaying this:
Users
-----------
User 1 - 30
User 2 - 25
Suppliers
-----------
Supplier 1 - £100
Your code seems fine. There is nothing wrong with having two instances of ArrayController. I made a jsbin based on your question and see users/suppliers in the right place. Check it out here: http://jsbin.com/ovitak/1/edit
Since your example didn't show how the data was being loaded, I implemented the refresh() methods to populate list of users/suppliers based on your expected output:
App = Ember.Application.create({});
App.userController = Ember.ArrayController.create({
content: [],
init: function() {
this.set('content', []);
this.refresh();
},
refresh: function() {
this.addObject({name: 'u 1', age: 22});
this.addObject({name: 'u 2', age: 35});
}
});
App.supplierController = Ember.ArrayController.create({
content: [],
init: function() {
this.set('content', []);
this.refresh();
},
refresh: function() {
//Refresh Action
this.addObject({name: 'supplier 1', revenue: 200});
}
});

Run jquery at the end of Ember.CollectionView rendering

I have a ContainerView which contains a CollectionView. After this CollectionView renders on the screen I need to perform a jquery function which essentially looks through the content of the rendered template and performs some display modifications.
If I perform that jquery within the didInsertElement of CollectionView it works but it gets executed for every single element in the CollectionView where as I really just need it to be done once at the end. How do I specify that?
http://jsfiddle.net/JFqNr/ (note doesn't render on jsfiddle or some reason but just to show you structure)
App = Ember.Application.create();
App.FooContainerView = Ember.ContainerView.extend({
childViews: ['elementList'],
elementList: Ember.CollectionView.extend({
content: function() {
return [
{ Title: "Dashboard", ID: "dashboard" },
{ Title: "Invoices", ID: "invoices" },
{ Title: "Expenses", ID: "expenses" },
{ Title: "People", ID: "people" },
{ Title: "Reports", ID: "reports" },
{ Title: "Settings", ID: "settings" }
];
}.property(),
template: Ember.Handlebars.compile( '{{view.content.title}}' ),
didInsertElement: function() {
// perform jquery function
}
}),
didInsertElement: function() {
// does not work if perforemed here
}
});
App.initialize();
​
The functionality to do this has only very recently been added to the master branch, so you will need to be compile your own version of Ember.
You can now schedule into an afterRender queue to run after all the individual views have been rendered.
App.FooContainerView = Ember.ContainerView.extend({
// Existing code
didInsertElement: function() {
Ember.run.scheduleOnce('afterRender', this, function(){
// perform jQuery function here;
});
}
See https://github.com/emberjs/ember.js/pull/1528 for code details.

ember.js how to set title of option for Ember.Select

I am a starter of Ember and I try to use Ember.js(1.0.0.pre) in my app.
I am trying to set title for my Ember.Select's options to show tips when mouseover.
But, I can't find any information about the option's title in API.
Do I have to write a function myself to populate the "title" attribute?
Is there any way like "optionLabelPath" to bind "title" attribute for options?
To achieve this we need to reopen the Ember.SelectOption
here is the fiddle for the following example
MyApp = Ember.Application.create();
Ember.SelectOption.reopen({
attributeBindings: ['title'],
title: function() {
var titlePath = this.getPath('parentView.optionTitlePath');
return this.getPath(titlePath);
}.property('parentView.optionTitlePath')
});
MyApp.selectArray = [{
label: "A",
id: "1",
title: "for Apple"
},
{
label: "B",
id: "2",
title: "for Ball"
}];
Handlebars
<script type="text/x-handlebars" >
{{view Ember.Select
contentBinding="MyApp.selectArray"
optionLabelPath="content.label"
optionValuePath="content.id"
optionClassPath="content.title"
}}
</script>​
​
Here is the simplest I could come up with:
http://jsfiddle.net/aK8JH/1/
Template:
{{view MyApp.Select contentBinding="content"}}
View:
MyApp.Select = Ember.Select.extend({
attributeBindings: ['title'],
title: 'myTitle'
});
Read this: http://emberjs.com/documentation/#toc_attribute-bindings-on-a-view
Below is what I've got after observing source code in Ember:
Ember.SelectOption.reopen({
attributeBindings: ['title'],
init: function() {
this.titlePathDidChange();
this._super();
},
titlePathDidChange: function() {
var titlePath = this.get('parentView.optionTitlePath');
if (!titlePath) { return; }
Ember.defineProperty(this, 'title', Ember.computed(function() {
return this.get(titlePath);
}).property(titlePath));
}.observes('parentView.optionTitlePath')
});