Toby Tremayne
Toby Tremayne

Reputation: 135

Ember multiple sendAction failing

Update below

Here's an interesting one. I have a template which contains a form component, and that form component's template also includes a component:

NewObj.hbs -> obj-form.js / obj-form.hbs -> file-uploader.js

The file uploader uses ember-uploader and it works great. I used its events to make sendAction calls to tell the obj-form controller that things are happening, IE pass on the upload progress percentage and indicate when the upload is complete.

If however I add one more sendAction, for some reason obj-form never receives the event for onComplete. No matter how I try it, it just never happens - no errors anywhere.

The file-uploader component is invoked in the obj-form template like so:

{{file-uploader
      url="/uploads"
      onProgress="fileUploadProgress"
      onComplete="fileUploadComplete"
      value=newProjectDownloadFile}}

file-uploader.js itself looks like this:

App.FileUploaderComponent = EmberUploader.FileField.extend({
  url: '',

  onProgress: 'onProgress',
  onComplete: 'onComplete',

  filesDidChange: function(files) {
    var uploadUrl = this.get('url');
    var that = this;
    var uploader = EmberUploader.Uploader.create({
      url: uploadUrl
    });

    uploader.on('progress', function (e) {
      that.sendAction('onProgress', e);
    });

    uploader.on('didUpload', function (response) {
      that.sendAction('onComplete', response);
    });
    if (!Ember.isEmpty(files)) {
      uploader.upload(files[0]);
    }
  }

});

And obj-form.js has these methods in the actions hash:

fileUploadProgress: function (e) {
    this.set('uploadPercentage', e.percent.toFixed(2));
},
fileUploadComplete: function (response) {
  this.set('newProjectDownloadFileUrl', response.url);
  this.set('newProjectDownloadFileName', response.fileName);
  this.send('addDownload');
},

It works great. But I wanted to make a progress bar only appear while uploading and disappear when upload was complete. I added the property uploadInProgress: false to the obj-form controller, and this:

isUploading: function () {
  return this.uploadInProgress;
}.property('this.uploadInProgress')

I use {{#if isUploading}} to show/hide the progress bar.

I added:

 this.set('uploadInProgress', false);

to the obj-form fileUploadComplete() method, and added this new method:

fileUploadStart: function () {
  this.set('uploadInProgress', true);
},

I modified the file-uploader component call to this:

{{file-uploader
      url="/connect/projectDownloads/file"
      onStart="fileUploadStart"
      onProgress="fileUploadProgress"
      onComplete="fileUploadComplete"
      value=newProjectDownloadFile}}

And changed file-uploader.js to look like this:

App.FileUploaderComponent = EmberUploader.FileField.extend({
  url: '',

  onStart: 'onStart',
  onProgress: 'onProgress',
  onComplete: 'onComplete',

  filesDidChange: function(files) {
    var uploadUrl = this.get('url');
    var that = this;
    var uploader = EmberUploader.Uploader.create({
      url: uploadUrl
    });

    uploader.on('progress', function (e) {
      that.sendAction('onProgress', e);
    });

    uploader.on('didUpload', function (response) {
      that.sendAction('onComplete', response);
    });
    if (!Ember.isEmpty(files)) {
      that.sendAction('onStart', true);
      uploader.upload(files[0]);
    }
  }

});

I've tried putting the that.sendAction('onStart', true); bit in all kinds of places in file-uploader.js but if that line exists, then the obj-form controller never receives the onComplete action. I have absolutely no idea why. I take that line out, it works again.

UPDATE ok I've found something new. It's not the sendAction that breaks it, it's this line in obj-form.js:

this.set('uploadInProgress', true);

For some reason, when I set that to true, it all falls apart. I'm wondering if I'm doing something wrong with the way I'm trying to make that work?

Could it be something to do with didInsertElement? I noticed that's getting triggered when I set uploadInProgress to true - because that property is being used to determine whether the progress bar appears on the page or not. So maybe I'm using didInsertElement incorrectly? Here's my didInsertElement and willDestroyElement:

   didInsertElement: function() {
   // console.log('didInsertElement');

   this.set( 'postType', this.get( 'content' ).get( 'postType' ) );
   this.set( 'projectDownloads', this.get( 'content' ).get( 'projectDownloads' ) );
   this.set( 'projectLinks', this.get( 'content' ).get( 'projectLinks' ) );
   this.set( 'published', this.get( 'content' ).get( 'published' ) );
   Ember.addObserver( this.get( 'content' ), 'postType', this, this.postTypeDidChange );
   Ember.addObserver( this.get( 'content' ), 'projectDownloads', this, this.projectDownloadsDidChange );
   Ember.addObserver( this.get( 'content' ), 'projectLinks', this, this.projectLinksDidChange );
   Ember.addObserver( this.get( 'content' ), 'published', this, this.publishedDidChange );
 },

  willDestroyElement: function() {
    console.log('willDestroyElement');
    Ember.removeObserver( this.get( 'content' ), 'postType', this.postTypeDidChange );
    Ember.removeObserver( this.get( 'content' ), 'projectDownloads', this.projectDownloadsDidChange );
    Ember.removeObserver( this.get( 'content' ), 'projectLinks', this.projectLinksDidChange );
    Ember.removeObserver( this.get( 'content' ), 'published', this.publishedDidChange );
  }

I've tried modifying isUploading to the alias style you recommended, but that hasn't helped anything. The idea is when that gets set to true, it makes the progress bar appear and the fileupload form disappear. Then when it gets set to false the reverse happens. I'm open to other ways to make this happen in Ember, I just can't figure out what I'm doing that's breaking things.

Upvotes: 1

Views: 173

Answers (1)

Kingpin2k
Kingpin2k

Reputation: 47367

Not the answer yet, but won't fit in comment correctly... this isn't necessary in the dependency chain, even easier is to change this to an alias.

From

isUploading: function () {
  return this.uploadInProgress;
}.property('this.uploadInProgress')

To

isUploading: Ember.computed.alias('uploadInProgress')

Upvotes: 1

Related Questions