3
votes

I have a utility class for validating usernames in my ember application and have it setup as specified in the ember-cli docs. I do client-side username validation in several places in my application (components and controllers) so I wanted to pull the validation logic out into a reusable method.

The file is at /app/utils/username-validator.js and I can successfully include the file in my app by importing it like so: import usernameValidator from 'my-app/utils/username-validator';

This works great so far and I've used the pattern for several utility classes. The problem I'm running into now is that I'd like the username-validator method to include a check to see if the username already exists.

As I am using Ember-Data I'd like to check the Ember-Data store. By default, the store appears to only be accessible in controllers and routes. How can I make it accessible in my utility class? All the injection examples I've seen deal with injecting the store into other first class Ember objects like components.

Is it possible to inject the store into a simple utility class as well?

Thank you!

I am using the following versions:

Ember-cli v0.2.6
ember.debug.js:4888 DEBUG: -------------------------------
ember.debug.js:4888 DEBUG: Ember             : 1.12.0
ember.debug.js:4888 DEBUG: Ember Data        : 1.0.0-beta.18
ember.debug.js:4888 DEBUG: jQuery            : 1.11.3
ember.debug.js:4888 DEBUG: Ember Simple Auth : 0.8.0-beta.2
ember.debug.js:4888 DEBUG: -------------------------------

===== Updated with detailed solution based on answer from torazaburo ======

Creating a service works great. Here is how I did it using ember-cli (v0.2.6) and ember v1.12.0

  1. Create your service inside of /app/services/<service-name>.js

The service blueprint will look like this (note the name of the service is based on the name of the file):

import Ember from "ember";

export default Ember.Service.extend({
   myFunction: function(){

   }
});
  1. Create an initializer for your service in /app/initializers/<service-name>.js which is used to inject your service into the different top level Ember objects (such as routes, controllers, components etc). Note that the file name of the initializer should match the file name of your service.

The blueprint for the initializer will look like this:

export function initialize (container, app) {
       // Your code here
}

export default {
  name: '<service-name>',
  initialize: initialize
};

To give a concrete example, lets say your service is called validator and contains a bunch of validation routines. You want to inject the validator into all controllers, and you also want to inject the Ember Data store into the validator itself. You can do it like this:

export function initialize (container, app) {
  // Inject the Ember Data Store into our validator service
  app.inject('service:validator', 'store', 'store:main');

  // Inject the validator into all controllers and routes
  app.inject('controller', 'validator', 'service:validator');
  app.inject('route', 'validator', 'service:validator');
}

export default {
  name: 'validator',
  initialize: initialize
};
1
Fine, but I would skip the initializer part, and instead just bring the service in wherever you need it with serviceName: Ember.inject.service. Actually, one of the advantages of services is that you don't need global injections in initializers and can just inject them directly wherever you need them. This approach is also what permits you to stub them when testing, which you can't do if you're doing global injections in initializers.user663031
I saw the Ember.inject.service and that looks pretty nice as well. I assume I still need the initializer to inject the store into the validator service though. Is that correct?Sarus
Yes, you have to inject the store into services in an initializer.user663031

1 Answers

3
votes

Make your utility into a "service", into which you can inject the store. Actually, it sounds like your utility should be a service anyway, even if it doesn't need the store. By making it a service, for instance, it becomes much easier to stub it out when writing tests. With a service, you need neither import anything nor do any global injections in initializers, you can simply say

export default Ember.Component.extend({

    myService: Ember.inject.service(), // inject services/my-service.js

    foo: function() {
         this.get('myService').api1(...);
    }

});