简体   繁体   中英

Ember.js checkbox and Promise

I have an issue when trying to use a checkbox to work out if a one-to-many relationship exists.

I have a userPrivilege table with userId, modelId, privilegeId and scopeId.

I am trying to display checkboxes which show whether the user has privileges. To do this, I need to check multiple conditions, not just a simple boolean field.

I can use asynchronous functions to determine whether the user has privileges, but I just don't know how to assign this to the checkbox 'selected'. Returning the promise means the checkbox is always checked. Returning the value from within the promise always leaves it unchecked.

See below a snippet of something I was attempting...

Checkbox Component:

    export default Ember.Component.extend({
          user: null,
          model: null,
          privilege: null,
          scope: null,
          selected: function() {
            return this.get('authorization').hasAuthorization(
              this.get('user.id'), 
              this.get('model'), 
              this.get('privilege'), 
              this.get('scope')).then(function(result) {
              return result;
            });
          }.property()
        })

Service:

export default Ember.Service.extend({
  hasAuthorization: function(userId, model, privilege, scope) {
    var store = this.get('store');

    return new Ember.RSVP.Promise(function (resolve, reject) {
      store.find('user', userId).then(function (user) {
        user.get('userPrivileges').then(function (userPrivileges) {
          userPrivileges.find(function (userPrivilege, index, userPrivileges) {
            userPrivilege.get('model').then(function (_model) {
              if (_model.get('name') === model) {
                userPrivilege.get('privilege').then(function (_privilege) {
                  if (_privilege.get('name') === privilege) {
                    userPrivilege.get('scope').then(function (_scope) {
                      if (_scope.get('name') === scope) {
                        resolve(true);
                      }
                    });
                  }
                });
              }
            });
          });
        });
      });
    });
  }
});

Edit: As per comment, I have now tried chaining, but now _privilege and _scope are undefined when the if statement isn't met (because no promise is returned). I think this could be done a lot better using some other structure, I just need to figure out how.

This now works, except that it doesn't resolve to false if the permission doesn't exist:

return new Ember.RSVP.Promise(function (resolve, reject) {
      store.find('user', userId).then(function (user) {
        if (!user) {
          return resolve(false);
        }
        return user.get('userPrivileges');
      }).then(function(userPrivileges) {
        if (!userPrivileges) {
          return resolve(false);
        }
        userPrivileges.forEach(function (userPrivilege) {
          userPrivilege.get('model').then(function (_model) {
            if (_model.get('name') === model) {
              return userPrivilege.get('privilege');
            }
          }).then(function (_privilege) {
            if (_privilege.get('name') === privilege) {
              return userPrivilege.get('scope');
            }
          }).then(function (_scope) {
            if (_scope.get('name') === scope) {
              console.log('true: ' + model + ' ' + privilege + ' ' + scope);
              return resolve(true);
            }
          }).catch(function(error) {
          });
        });
      });
    });

You just need to reject when you have an errror now and resolve your outer promise to false if one of those errors occur.

import Ember from 'ember';

export default Ember.Service.extend({
  hasAuthorization: function (userId, model, privilege, scope) {
    var store = this.get('store');

    return new Ember.RSVP.Promise(function (resolve, reject) {
      store.find('user', userId).then(function (user) {
        if (!user) {
          return resolve(false);
        }
        return user.get('userPrivileges');
      }).then(function(userPrivileges) {
        if (!userPrivileges) {
          return resolve(false);
        }
        return resolve(userPrivileges.find(function (userPrivilege, index, userPrivileges) {
          userPrivilege.get('model').then(function (_model) {
            if (_model.get('name') === model) {
              return userPrivilege.get('privilege');
            }
            return Ember.RSVP.reject();
          }).then(function (_privilege) {
            if (_privilege.get('name') === privilege) {
              return userPrivilege.get('scope');
            }
            return Ember.RSVP.reject();
          }).then(function (_scope) {
            if (_scope.get('name') === scope) {
              return Ember.RSVP.resolve(true);
            }
            return Ember.RSVP.reject();
          }).then(null, function(error) {
            return Ember.RSVP.resolve(false);
          });
        }));
      });
    });
  }
});

then takes a second argument that handles errors. https://github.com/tildeio/rsvp.js/#basic-usage

When chaining, the second argument is called if any of the previous methods of the chain rejected.

In this case we want to resolve the original promise to false if a rejection occurs.

Update: Addressed issue where find might return undefined.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM