Search code examples
ember.jsember-bootstrap

Correct way to use actions with ember-bootstrap


Created a new ember octane app (3.15) and using ember-bootstrap with it. I am using a modal like so

<BsModalSimple
  @open={{true}}
  @title="Create new podcast"
  @closeTitle="Cancel"
  @submitTitle="Create"
  @size="lg"
  @closeButton={{false}}
  @fade={{false}}
  @backdrop={{true}}
  @backdropClose={{false}}
  @renderInPlace={{false}}
  @onHidden={{action 'closeModal'}}
  @position="center">
</BsModalSimple>

This works but I get an error which says

Do not use action as {{action ...}}. Instead, use the on modifier and fn helper.

What's the right way to use an action in this scenario? I've tried this but it didn't work

{{on 'hidden' this.closeModal}}

Solution

  • In classic Ember model (pre-octane), the {{action}} helper was used to bind the proper this context to the action/method that is being passed as a closure action. So, when the closure action is called inside any class, the action will have the caller's this context not the callee.

    To be more predictable and explicit, this context binding was moved as a decorator, @action which should be used to decorate your closeModal method instead of using the {{action}} helper in the template. So, your code can be:

    <!-- application.hbs -->
    
    <BsModalSimple
      @open={{true}}
      @title="Create new podcast"
      @closeTitle="Cancel"
      @submitTitle="Create"
      @size="lg"
      @closeButton={{false}}
      @fade={{false}}
      @backdrop={{true}}
      @backdropClose={{false}}
      @renderInPlace={{false}}
      @onHidden={{this.closeModal}}
      @position="center">
    </BsModalSimple>
    
    // controllers/application.js
    
    import Controller from "@ember/controller";
    import { action } from "@ember/object";
    
    export default class ApplicationController extends Controller {
      @action
      closeModal() {
        // your implementation
      }
    }
    

    Please note that the error was thrown by the linter (ember-template-lint) and the error message can be more explicit to use the @action decorator.