This week we created a very basic service that we then injected into a single component. We then used an initializer to inject the service into all of our controllers, routes, and models. Today we are going to look at modifying data on a service by way of an action which will call a method on the service.

In our contrived example here, let's say that our current-user can send a total of 10 messages. We want to store a count of the remaining messages on our current-user service.

In app/services/current-user.js add a messagesRemaining property and we will set it to 10. Let's also add a function to decrement the messagesRemaining count. This function will check that we have messagesRemaining. If we do we will decrement our messagesRemaining property and send back an object with a success value set to true and a message value set to some informative string. If we don't have any messagesRemaining, we don't want to decrement the property, we just want to send back an object with success set to false and a message about the problem.

import Ember from 'ember';

export default Ember.Service.extend({
  messagesRemaining: 10,
  userInfo: Ember.Object.create({
    id: 1,
    firstName: 'Brandon',
    lastName: 'Blaylock',
    email: 'brandon.blaylock@gmail.com',
    twitter: 'baroquon',
    github: 'baroquon',
  }),
  decrementMessagesRemaining(){
    if(this.get('messagesRemaining') > 0){
      this.decrementProperty('messagesRemaining');
      return { success: true, message: `You have ${this.get('messagesRemaining')} messages remaining.` };
    } else {
      return { success: false, message: `You are out of messages.` };
    }
  }
});

We can call this from our component by adding an action on the component that calls this function. So, let's create a component that has a textarea that takes in a message and has a button to send the message.

ember g component send-message

In app/templates/components/send-message.hbs

{{notice}}
<br>
{{textarea value=messageText}}
<button {{action 'sendMessage' messageText}}>Send Message</button>

In app/components/send-message.js first we are going to inject our service. Then we will create an action that takes in a message and checks if the message exists. If it exists we will call the function on our service that decrements our message count. As we saw in the service, this function returns an object with a success key and a message key so we are saving that return value to the variable sendMessage. If sendMessage.success is true, we want to reset the textarea which we do by setting the value to an empty string. This is also where we could put some message sending logic. Then finally we sent the notice on our component to the message value on the object that we got back from the function on our service.

currentUser: Ember.inject.service(),
actions: {
  sendMessage(messageText){
    if(Ember.isPresent(messageText)){
      let sendMessage = this.get('currentUser').decrementMessagesRemaining();
      if(sendMessage.success){
        this.set('messageText', '');
      }
      this.set('notice', sendMessage.message);
    } else {
      this.set('notice', 'You should really type a message before you send one.');
    }

  }
}

Finally, let's add our new component to our application template:

{{send-message}}

Now, if we look at our site, we can see our message textarea. We can send a message and we get a notice of how many messages we have remaining, if we try to send a message without text we will get a notice that we can't do that because we used Ember's isPresent helper. Finally, if we have sent all of our allotment of messages we will receive a notice that we don't have any messages left to send.

That is it for today. Tomorrow we will look at some links and an exercise to allow us to build on our work. See you then.

Tags

actions, services, injection