Only show if button when model is saved

I am gettring rid of my ‘ifEqual’ hacks with computed properties and also wanted to clean up some variable settings.

The problem: The user can switch between ‘Published’ and ‘Unpublished’, if it’s unpublished he is also able to delete the content. But the ‘Delete’ Button only should be there if he saves the content with ‘unpublished’.

The binding is a problem here, because if I do it with a property like:

isUnpublished: Ember.computed.equal('status', 'unpublished'),

of course, he immediately shows the ‘Delete’ button.

What’s the best way to handle these things?

EDIT: Sure, I could set and unset a variable like ‘readyForGarbage’ in my functions, but imo this couldn’t be the right way

I’ve been meeting to figure out a way to inject ember-buffered-proxy into Ember Data Models but just haven’t gotten the time yet. Sounds like you might want something similar. So basically changes made to a Model will not propagate throughout ember until it is saved to the server.

You could look at the isDirty property on the Model. So something like this:

// app/model/foobar.js
import Ember from 'ember';
import DS from 'ember-data';

export default DS.Model.extend({
    status: DS.attr('string'),
    unpublished: Ember.computed.equal('status', 'unpublished'),
    isSaved: Ember.computed.not('isDirty'),
    isUnpublished: Ember.computed.and('unpublished', 'isSaved')
});

But it sounds like you are trying to move away from too many computed properties.?.

1 Like

I probably wrote that wrong, I actually want to use computed properties instead of my own handlebar helpers for ifs :smile:

I tried it this, but still have one problem: My ‘status’ is a ‘belongsTo’ attribute - so the isDirty attribute of my model doesn’t change

Tried using ember-buffered-proxy directly on models, haven’t had much success with that. Here’s the approach I’m using (still needs a bit of work to continue working under Ember 2.0):

import Ember from 'ember';
import BufferedProxyMixin from 'ember-buffered-proxy/mixin';

export default Ember.Component.extend({
  isEditing: false,
  content: {}, // the "new" model instance to work on
  model: null,

  article: function() {
    var article = Ember.ObjectProxy.createWithMixins( BufferedProxyMixin, {
      content: this.get('content')
    });
    article.initializeBuffer();
    if ( article.get('id') ) {
      this.disableEditMode();
    } else {
      this.enableEditMode();
    }
    return article;
  }.property('content'),

  enableEditMode: function() {
    this.set( 'isEditing', true );
  },

  disableEditMode: function() {
    this.set( 'isEditing', false );
  },

  actions: {

    edit: function() {
      this.enableEditMode();
    },

    save: function() {
      this.disableEditMode();
      this.get('article').applyBufferedChanges();
      this.sendAction( 'save', this.get('content') );
    },

    create: function() {
      this.disableEditMode();
      this.get('article').applyBufferedChanges();
      this.sendAction( 'create', this.get('content') );
    },

    delete: function() {
      this.disableEditMode();
      this.sendAction( 'delete', this.get('content') );
    },

    revert: function() {
      this.disableEditMode();
      this.get('article').discardBufferedChanges();
      this.sendAction( 'revert' );
    },

    cancel: function() {
      this.disableEditMode();
      this.get('article').discardBufferedChanges();
      this.sendAction( 'cancel' );
    }

  }
});

Used like this for existing articles:

{{article-editing
  content=model
  save='saveArticle'
  delete='deleteArticle'
}}

Or for new articles:

{{article-editing
  create='createNewArticle'
  cancel='returnToArticles'
}}

My routers look like:

import Ember from 'ember';

export default Ember.Route.extend({
  actions: {
    saveArticle: function( article ) {
      article.save().then( function() {
        article.reload();
      });
    },

    deleteArticle: function( article ) {
      var self = this;
      article.destroyRecord().then( function() {
        self.transitionTo( 'articles' );
      });
    }
  }
});

Probably not perfect, but maybe it helps :smile:

Thanks @Leeft, I’ll review your stuff in the morning. Bummer on the ember-buffered-proxy, I had some hope…

Just thought of another tactic I’m going to try. Instead of the html form modifying the model directly, I’ll have it modify properties on the controller. Those properties will Ember.computed.oneWay() to the model properties, to get the default/current values. Then on form submit, the action handler will apply the (potentially) changed properties from the controller to the model, try .save()ing the model right away and .rollback() if it fails. Of course there will be a short period where the changes will appear throughout Ember while the changes are saved… Example: JS Bin - Collaborative JavaScript Debugging

Well, I am using buffered-proxy, just not directly applied to the model class. Instead I wrap the model with it within my component.

Ah, I see. Almost like a container for the changes. I meant bummer on the buffer on a model directly. What issues did you run into?

I can only remember I had a good reason, now if only I could remember the actual reason … :frowning: