How to use adapter in an ember-engines - ember.js

as the title says, I have some problems understanding how to use an adapter in an ember-engines.
I am currently running my application with ember#2.15, ember-data#2.15 and ember-engines#0.5.14.
I already used an adapter in my main application, but if I tried to reproduce a basic adapter in my application, the page is loading indefinitely.
In my route, I call my adapter with the findAll method:
model()
{
"use strict";
console.log('In my route');
return this.get('store').findAll('my-adapter-name', {reload: true});
}
And in my adapter, I respect the syntax that I used in my in-app adapter:
import DS from 'ember-data';
import Ember from 'ember';
export default DS.Adapter.extend({
findAll: function (store, type, sinceToken, snapshotRecordArray)
{
console.log("In my adapter");
return new Ember.RSVP.Promise(function (resolve, reject)
{
// I accede to my websocket service here, nothing to do with my question
});
},
/* *
* My other function, like findRecord, ect...
*/
});
As you can see, I put some console.log in my code, and I can access the message in my route, which is in my engine, but I can't access the message in my adapter, which is also in my engine.
I tried to put a console.log in an adapter in my application, and the message is properly shown, so I am sure this is because I can't access to the adapter in my engine, so if anybody has an idea to how we should configure our adapter in our ember-engines, this would be very appreciated.
For your information, this is an in-repo engines.

Just found it, this is a bit tricky, but your models (and adapters) should be in the myApp/lib/myEngine/app/models/, and not in myApp/lib/myEngine/addon/models.
I don't know if this is intended this way, but this is the only way I found to add model in your in-repo ember-engines.
EDIT
This will do the trick for the serializers and the transform.

Related

How can I extend DS.Store in an Ember Application?

I want to add a function to the store as part of a web sockets plugins I am working on.
As part of this, I need to extend the store (DS.Store).
I have tried putting the following file in both app/store.js & app/stores/application.js but this does not seem to work.
import DS from 'ember-data';
export default DS.Store.extend({
init: function() {
console.log('Using custom store!');
return this._super.apply(this, arguments);
}
});
Do I need to put this somewhere else?
Turns out that in order to extend the store you need to make a service called store.js.

Possible to make a route transition inside of a service in Ember?

I'm using ember-cli 1.13.8 and I have a service that handles most of my logic. Right now I have a function that listens to whether certain things are true or false and then can make a route change based upon that. I'd rather not have to call that function from inside every route since I want it to happen on every route. Its goal is to determine whether the player won and every interaction in the game drives this.
Inside of my game service:
init() {
...
if(true) {
console.log("you've won!");
this.transitionTo("congratulations");
}
},
Of course, this fails because this isn't a route like Ember expects. I know I can call this method from inside of every route instead but I'm wondering if there is a better way to do this.
Thanks
Edit
So far I've tried importing in the App and then trying to extend the Router. This seems like a bad idea though.
You can use the routing service (which is a private API):
routing: Ember.inject.service('-routing'),
init() {
...
if(true) {
console.log("you've won!");
this.get("routing").transitionTo("congratulations");
}
},
As of Ember 2.15, there is a public router service for exactly this use case. Just add router: Ember.inject.service(), to your Ember class and call this.get('router').transitionTo(...);, easy!
Generally this is a bad idea, but in some cases it's easier than passing through route actions in 100 places (personal experience).
The better way to do this from anywhere is to look the router up on the container:
Ember.getOwner(this).lookup('router:main').transitionTo(...);
this has to be some container allocated Ember object, which includes components, services, and Ember Data models.
Note also that if this will be called a lot, you will want to store the router as a property. You can do this in the init hook:
init() {
this._super(...arguments);
this.set('router', Ember.getOwner(this).lookup('router:main'));
}
...
this.get('router').transitionTo(...);
Ember.getOwner(this) works in Ember 2.3+, prior to that you can use this.get('container') instead.
Ember 1.13:
Create another service called routing:
import Ember from 'ember';
export default Ember.Service.extend({
_router: null,
init() {
this._super();
this.set('_router', this.get('container').lookup('router:main'));
},
transitionTo() {
this.get('_router').transitionTo(...arguments);
}
});
Then you can:
routing: Ember.inject.service(),
goSomewhere() {
this.get('routing').transitionTo('index');
}

Accessing Ember Controller Properties within the same controller

I'm very new to EmberJS 2.0 and trying to slowly understand it by building my own website with it. Anyways, I've managed to get Firebase integrated with Ember and my controller is able to authenticate correctly. However, I'd like to understand why when I execute:
this.send('toggleModal');
inside the authenticate action property function (.then()) it doesn't work but if I execute it outside then everything works fine.
1) Is the 'this' keyword getting confused with something other than the Ember controller?
Here is the sample:
// /app/controllers/application.js
import Ember from 'ember';
export default Ember.Controller.extend({
isShowingModal: false,
actions: {
toggleModal: function() {
this.toggleProperty('isShowingModal');
},
authenticate: function(username, pass) {
this.get('session').open('firebase', {
provider: "password",
email: username,
password: pass
}).then(function (data) {
console.log(data.currentUser);
console.log(session.isAuthenticated); //Why is 'session' not defined?
this.send('toggleModal'); //This doesn't work. Throws an error.
});
this.send('toggleModal'); //This works.
},
logOut: function() {
this.get('session').close();
}
}
});
2) Also, I've noticed that when using Emberfire I'm able to use the property 'session.isAuthenticated' within the template application.hbs however, shouldn't 'session' be an object that is injected to all routes and controllers using Torii? Why is that property inaccessible/undefined within the application.js controller? I'm using https://www.firebase.com/docs/web/libraries/ember/guide.html#section-authentication as a reference.
3) In the guide above the actions for authentication are put inside the route. However, according to this quora post the route should only handle template rendering and model interfacing. Is this post incorrect? The authentication logic should reside in the application.js controller correct? https://www.quora.com/What-is-the-best-way-to-learn-Ember-js
1) Is the 'this' keyword getting confused with something other than the Ember controller?
Yes. This is one of the most common sticking points of Javascript. There's a lot of articles out there about it, but this one looked pretty good. To solve it you'll either need to use an arrow function, bind the function to the current context, or save the context in a local variable. (Read that article first though.)
2) Also, I've noticed that when using Emberfire I'm able to use the property 'session.isAuthenticated' within the template application.hbs however, shouldn't 'session' be an object that is injected to all routes and controllers using Torii? Why is that property inaccessible/undefined within the application.js controller? ...
That's because the template pulls the property from the current context (your controller). Inside of your controller you'll have to use this.get('session') instead. (After you fix the issue I mentioned above.)
3) ... Is this post incorrect? ...
I wouldn't say incorrect, just a bit oversimplified. I would follow whatever conventions the library uses as that's probably the best way given the library's requirements.
You're partially right about this although it's not really confused. this (where you're modal call doesn't work) isn't scoped to the Controller anymore, because it's inside a function. Either:
replace the function (data) call with data => if you're using ember cli. Or
var _self = this; up top and reference _self instead.
This should at least get you started.

How to use a library to fetch data in Ember

I am still very new to the world of Ember, and I'm still trying to understand EmberJS and Ember Data (latest version). In my previous (non-Ember) Node app, I included a library that handled all my REST calls to where my data was stored. It set up the connection to the server and handled all the error handling and parsing into a nice and tidy JSON object, and even handled multiple calls to the server in case the response was too big for one call. I can fetch individual records, but if I wanted to fetch a bunch of records, all I had to do was initialize the library object ('myObj') and call myObj.fetchAll(config) to initiate the fetch. Then I just have to wait on several events.
Example
myObj.on('record', function() { // Each record is an event }
myObj.on('error', function () { ...}
myObj.on('end', function () { // After the last record is retrieved }}
I would very much still like to use this library in Ember, but I have no idea how to go about setting it up. I haven't been able to find any examples of creating my own Adapter (is that the right terminology) that would allow me to do this.
Is this something I can do with Ember, or is it not recommended?
I would strongly suggest you use ember-data before attempting something non-standard as you're learning. Virtually all the documentation, and help will specifically be about ember-data. This is a good starting point: http://guides.emberjs.com/v1.13.0/models/
It's perfectly possible to use your own models and use a custom rest interface. You initiate your myObj.fetchAll(config) call on the router. If it's waiting for an event, return a promise and resolve it when the event returns. I don't know anything about your library but it would look something like:
export default Ember.Route.extend({
model() {
return Ember.RSVP.Promise(function(resolve){
var records = [];
myObj.on("record", (record) => {
records.pushObject(record);
});
myObj.on("end", () => {
resolve(records);
});
myObj.fetchAll(ENV.config);
});
}
});
In imperfect contrast, this is how you glue things together from your adapter to your template normally in ember:
Configuring a REST endpoint:
export default DS.RESTAdapter.extend({
host: 'https://api.example.com'
});
Defining a model:
export default Model.extend({
name: attr('string')
});
Fetching data in your route:
export default Ember.Route.extend({
model() {
return this.store.findAll('person');
}
});
Rendering the data:
{{#each model as |person|}}
{{person.name}}
{{/each}}
It's all pretty straight forward if you stick to the default way of doing things.

Ember 1.12 Inject Route into Service

I'm trying to create a service to handle modal dialogs in Ember 1.12 with Ember-cli. Maybe a service isn't the best way to approach this, but I want to access it from just about anywhere in the app, and be able to dynamically insert content into the popup, so it seemed like the right way to go.
Here is my service:
import Ember from 'ember';
export default Ember.Service.extend({
route: Ember.inject.service('route'),
open: function(content){
console.log('open popup', content);
this.get('route').render('popup-box', { //popup-box is a component
into: 'application',
outlet: 'popup'
});
},
close: function(){
//TODO
}
});
When I call the open method, I get this error:
Uncaught Error: Attempting to inject an unknown injection:
service:route
I'm not sure what I'm missing. Suggestions?
You should check out ember-wormhole, https://github.com/yapplabs/ember-wormhole. It will let you target a section of your template to an anchor somewhere else in the dom. It's perfect for modals!
Additional Info:
AS #runspired pointed out, you can't inject the router like you have it.
If you did want to inject the router, you could do so with Ember.inject.service('-routing') or via application.inject('<myTarget>', 'router', 'router:main'); from an initializer.
However, you do not have access to a render method and this could be considered a smell.