Reputation: 2765
I have Ember displaying a list of things.
I want the user to upload a file and change the list of things to the stuff in that file.
HTML
<script type="text/x-handlebars" id="index">
<h2>List of things</h2>
<ul>
{{#each item in model}}
<li>{{item}}</li>
{{/each}}
</ul>
Change List of Things:
{{#view Ember.View}}
{{view App.FileUp}}
{{/view}}
</script>
Javascript
App = Ember.Application.create();
App.Router.map(function() {
// put your routes here
});
App.IndexRoute = Ember.Route.extend({
model: function() {
return ['red', 'yellow', 'blue'];
}
});
App.ApplicationController = Ember.Controller.extend({
actions: {
file_upload: function(data) {
alert("I want to change the model to: " + data);
}
}
});
App.FileUp= Ember.TextField.extend({
type: 'file',
change: function(evt) {
var input = evt.target;
if (input.files && input.files[0]) {
var that = this;
var reader = new FileReader();
reader.onload = function(e) {
var data = e.target.result;
var c = App.ApplicationController.create();
c.send('file_upload', data);
}
reader.readAsText(input.files[0]);
}
},
});
At the line with the alert, I have access to the text from the uploaded file, and I'm in the application controller. How can I change the model so that the list of the page reflects what's in the text file?
JS Fiddle: http://jsfiddle.net/LJx9t/
If this code isn't idiomatic Ember, please feel free to correct.
Upvotes: 2
Views: 626
Reputation: 47367
Being a component you should use sendAction
to pass the action out of the component. This allows the component to be used multiple times and doesn't tie it to the context.
{{view App.FileUp uploadComplete='file_upload'}}
{{view App.FileUp uploadComplete='file_upload2'}}
Then inside your component
change: function(evt) {
var input = evt.target,
self = this;
if (input.files && input.files[0]) {
var that = this;
var reader = new FileReader();
reader.onload = function(e) {
var data = e.target.result;
self.sendAction('uploadComplete', data);
}
reader.readAsText(input.files[0]);
}
},
then your action gets sent to the controller, then route, then up the route tree until it's handled.
Create an index controller to handle it
App.IndexController = Ember.Controller.extend({
actions: {
file_upload: function(data) {
this.set('model', data.split('\n'));
},
file_upload2: function(data) {
alert(data);
}
}
});
Upvotes: 2
Reputation: 11671
The model you want to change has been created by the IndexRoute
, so you need to set it to the IndexController
. Furthermore the App.FileUp
is a component, so in order to send the action to the currently active controller, which is IndexControler
it is required to use targetObject
or get('controller')
from parentView
.
(related info, https://github.com/emberjs/ember.js/blob/master/packages/ember-handlebars/lib/controls.js#L81-84 and a discussion https://github.com/emberjs/ember.js/issues/3393 )
So assuming a file with csv is uploaded the following code can achieve what you require,
js
App = Ember.Application.create();
App.Router.map(function() {
// put your routes here
});
App.IndexRoute = Ember.Route.extend({
model: function() {
return ['red', 'yellow', 'blue'];
}
});
App.IndexController = Ember.ObjectController.extend({
actions: {
file_upload: function(data) {
alert("I want to change the model to: " + data);
this.set('model',data.split(","));
}
}
});
App.FileUp= Ember.TextField.extend({
type: 'file',
change: function(evt) {
var self = this;
var input = evt.target;
if (input.files && input.files[0]) {
var that = this;
var reader = new FileReader();
reader.onload = function(e) {
var data = e.target.result;
//self.get('parentView').get('controller').send('file_upload', data);
self.get('targetObject').send('file_upload', data);
}
reader.readAsText(input.files[0]);
}
},
});
Upvotes: 1