javascriptember.jsember-dataember-componentsember-controllers

how to pass controller data into component and back up in ember js


I have an ember 2.13 app that has a users route fetching a users model. So in the users template I am showing all the users fetched. I also have a users controller that feeds data to an edit form when a user is clicked. I'm using the user controller to do this.

All the code is in a single template but I would like to put the rendering user list and edit user form in two separate components. Let's say I make a render-single-user and edit-user templates. So when a user clicks on a user in rendered using the render-single-user component, data of this user should show up in the dom rendered by edit-user component.

The problem is a component doesn't have access to the route's model or the app's store.

I would be grateful if someone would tell me how to pass the model and store from controller to the components and also between the render-single-user and edit-user components. And when a user clicks update/save the modified data should travel up to the controller and save the record to the store consequently making a post request to the server.

Screenshots attached.

User View

enter image description here

Clicked User

enter image description here


Solution

  • This answer applies to versions 2.x.x and was written as of 2.15.

    It sounds like you're just getting started in Ember. Welcome! I highly encourage you to do the Tutorial and read The Guides. They are an investment - things will go much faster and be much easier for you afterwards. Everything I'm about to tell you is available there. They are not skippable.

    In your users route:

    model() {
       return this.store.findAll('users')
    }
    

    In your users controller:

    actions: {
      consoleLogger(thingToLog) {
        console.log(thingToLog)
      }
    }
    

    Data and actions are passed from controllers and routes down to components. This is done through the handlebars templates.

    Generic example of passing actions, model, and variables to a component:

    {{some-component 
       someControllerVariable=someControllerVariable
       mode=model 
       consoleLogger=(action "consoleLogger")}}
    

    Then in your component, you can either use the action like this:

    <button {{action consoleLogger "string to log"}}>Log it</button>
    

    Or use it in your component js like this:

    this.get('consoleLogger')("string to log");
    // this.get retrieves the function and then we call it with an argument, kind of like how you'd do someOtherFunction() in plain js
    

    Since you need to show a list of helpers, you will need to use the each helper in your route:

    {{#each users as |user|}}
           {{user-list-item 
           someControllerVariable=someControllerVariable
           user=user 
           consoleLogger=(action "consoleLogger")}}
    {{/each}}
    

    When the action is used in your component, you can pass records as arguments. They'll go to the controller action and that's where you should do your POST/PATCH/DELETE type operations like save().

    Good luck :)