Detect if `belongsTo` is null, and toggle associations

I am missing something about how to determine if a belongsTo relationship on a model is set. And how I can toggle that association between an existing, persisted instance and a new, unpersisted instance?

I have a new Project entity created in a route like this:

model() {
  return this.store.createRecord('project', {
    team: this.store.createRecord('team', { name: 'New Team' }),
  });

I have a component where I would like to implement a UI where the user can select an existing team and assign it to the project. But, they might want to change their mind and revert back to a new, unpersisted team. (the persistence of the team is handled on the server.)

Adding an account (using the addTeamMember action below) works when the form is initially loaded with a new, unpersisted team. It works when a persisted team is selected (e.g. a call to setTeam where team is a persisted Team models), but after a call to setTeam with null. I am unable to “reassign” a new Team instance to the model and a subsequent call to addTeamMember fails.

The form component has two @actions.

  @action
  setTeam(team) {
    // team may be a persisted team OR null
    this.args.model.set('team', team);

   // interestingly, I have tried...
   // console.log('before set');
   // console.log(this.args.model.team);
   // this.args.model.team = team;
   // console.log('after set');
   // console.log(this.args.model.team);
   // and, the Proxy item in the console appears to be identical?
  }

  @action
  addTeamMember(acct) {
    let ta = this.store.createRecord('teamAccount', {
      account: acct,
    });

    // I can not figure out the boolean check to add a temporary
    // team back to the model
    if (this.args.model.team === null) {
      console.log("creating a new team for the project");
      this.args.model.set('team', this.store.createRecord('team', {
        org: this.args.model.org,
      }));
    }

    // after a call to `setTeam` above with the parameter null, this fails because the
    // if check above never was executed and an error of `team.get(... is undefined` is the result.
    this.args.model.team.get('teamAccounts').pushObject(ta);
  }

When you just reference a relationship (or at least an async relationship) it’s going to return a special promise, which of course will never be null. I think the easiest way to do what you want is to use the lower-level BelongsToReference API, specifically the value method.

So if you change your code from this:

    if (this.args.model.team === null) {

to this:

    if (this.args.model.belongsTo('team').value() === null) {

It should be more along the lines of what you want

2 Likes

Thank you, that worked perfectly. I feel like I’ve been circling that solution for hours!

1 Like

That API is fairly well documented, but IIRC mostly in the API docs section and not the main guides, so it’s not always easy to find. It’s pretty powerful if you’re doing any more advanced relationship management type stuff. It’s really handy if you need to check a related record id without triggering any async fetch, for example. Or if you want to force refetch a relationship for whatever reason.

1 Like