How to refresh model data from inside component in EmberJS? - ember.js

Currently I have a set up a application that lists the model collection and also have implemented pagination in it.
Now, I want to move all of this logic into a component so that it is reusable across multiple listings. To achieve this, I have passed the model variable inside the component.
Since, server data communication is considered a bad practice I assume the changes must be applied to the controller ?
So, I am confused on how to make the api call to refresh the data can be called ?

You can build method in controller and pass them as method in the required components. This way, you can avoid data call in component and make it reusable.
eg:
{{some-list getData=getSomeListData}}
where getSomeListData applies the required data changes.

Related

architecture question - using sub routes vs components

I am trying to build a UI with left side bar having filters and right side having actual filtered data.
For loading data into the dynamic part of the UI(right side), which approach is considered better in terms of code quality and app performance ?
Use sub routes (for dynamic part of the UI)
Use separate components that load their own data (for dynamic part of
the UI)
There is not a direct correct answer for that; you can use both ways but here is a few things to consider and in the end I generally prefer to use sub-routes due to the following:
Waiting for UI to load: In case you are using separate components to load their own data; then you need to handle the loading state of the components. What I mean is; if you simply use sub-routes; then model hooks (model, beforeModel, etc.) will wait for the promises to be solved before displaying the data. If you simply provide a loading template (see the guide for details) it will be displayed by default. In case you use components, you might need to deal with displaying an overlay/spinner to give a better UX.
Error Handling: Similarly like loading state management; Ember has already built in support for error handling during route hook methods. You will need to deal with that on your own if you prefer components to make the remote calls. (See guide for details)
Application State: Ember is SPA framework; it is common practice to synchronize application state with the URL. If you use sub-routes; you can simply make use of the query parameters (see the guide for details) and you will be able to share the URL with others and the application will load with the same state. It is a little bit trickier to do the same with components; you still need to use query parameters within the routes and pass the parameters to the components to do that.
Use of component hook methods: If you intend to use the components then you will most likely need to use component hook methods to open the application with default filter values. This means you will need to make some remote call to the server within one or more of init, willRender, didReceiveAttrs component hook methods. I personally do not like remote calling within those methods; because I feel like this should better be done within routes and data should be passed to the components; but this is my personal taste of coding that you should approach the case differently and this is perfectly fine.
Data down, actions up keeps components flexible
In your specific example, I'll propose a third option: separate components that emit actions, have their data loaded by the route's controller, and never manipulate their passed parameters directly in alignment with DDAU.
I would have one component, search-filter searchParams=searchParams onFilterChange=(action 'filterChanged'), for the search filter and another component that is search-results data=searchResults to display the data.
Let's look at the search filter first. Using actions provides you with maximum flexibility since the search filter simply emits some sort of search object on change. Your controller action would look like:
actions: {
filterChanged(searchParams){
this.set('searchParams', searchParams);
//make the search and then update `searchResults`
}
}
which means your search-filter component would aggregate all of the search filter fields into a single search object that's used as the lone parameter of the onFilterChange.
You may think now, "well, why not just do the searching from within the component?" You can, but doing so in a DRY way would mean that on load, you first pass params to the component, a default search is made on didInsertElement which emits a result in an action, which updates the searchResults value. I find this control flow to not be the most obvious. Furthermore, you'd probably need to emit an onSearchError callback, and then potentially other actions / helper options if the act of searching / what search filter params can be applied together ever becomes conditionally dependent on the page in the app.
A component that takes in a search object and emits an action every time a search filter field changes is dead simple to reason about. Since the searchParams are one-way bound, any route that uses this component in it's template can control whether a field field updates (by optionally preventing the updating of searchParams in an invalid case) or whether the search ever fires based of validation rules that may differ between routes. Plus, theres no mocking of dependencies during unit testing.
Think twice before using subroutes
For the subroutes part of your question, I've found deeply nested routes to almost always be an antipattern. By deeply, I mean beyond app->first-child->second child where the first child is a sort of menu like structure that controls the changing between the different displays at the second child level by simple {{link-to}} helpers. If I have to share state between parents and children, I create a first-child-routes-shared-state service rather than doing the modelFor or controllerFor song and dance.
You must also consider when debating using children route vs handlebars {{if}} {{else}} sections whether the back button behavior should return to the previous step or return to the route before you entered the whole section. In a Wire transfer wizard that goes from create -> review -> complete, should I really be able to press the back button from complete to review after already having made the payment?
In the searchFilter + displayData case, they're always in the same route for me. If the search values need to be persistent on URL refresh, I opt for query params.
Lastly, note well that just because /users/:id/profile implies nesting, you can also just use this.route('user-profile', { 'path' : 'users/:id/profile' }) and avoid the nesting altogether.

How can I model singletons without an id in ember?

I am new to ember and am trying to migrate an existing application, and would like to know what the recommendation is for modeling a single object that will be reused in multiple components on every page. ie: As part of the initial load, I would like to perform a GET request against a URL like 'https://example.com/currentUser' and get an object back like:
{
name: "Users Name"
email: "user#email.com",
profileImg: "http://example.com/pictureOfUser.png"
... snip ...
}
This object will then be used in components for menus, toolbars, and a form for updating it via a post to the same URL.
What is the best way to model this workflow in ember? Given that this is an incidental object and not the focus of most routes, it does not seem to make sense to specify it as the model of them. Also, does ember data handle cases where a model is a singleton and does not have an ID, or would I need to use something like Ember.$.ajax ?
What do you mean by "where a model is a singleton"?
If you use the ember-data default adapter, then yes, a model needs to have an ID, it's part of the JSONAPI spec. If you already have a backend with different conventions, take a look at extending or swapping out the default adapter.
A service is a singleton, and there is nothing preventing you from making an AJAX call there. You would be losing out on all the nice things that come along with ember-data, but, you can do it.

Can’t update existing view with each-in helper

We are creating a Sportsbook web app using Emberjs, where we retrieve data through an API and draw the view.
The received data is an object with many nested levels. Based on this object we have constructed the template file(.hbs) using each-in helper!
We are unable to use 'each' helper as we are receiving object, not array!
After the first retrieval, we are receiving updates every milliseconds and need to update the view as well by changing only the difference.
Sometimes we are receiving new entries in the object, and as the object itself is big, we need to add the new entry to the layout without redrawing the whole stuff.
Here is the problem: Each-in is not observable in this case, so it is not redrawing after pushing the new object.
Question: Is there a good way to implement this with Ember or is there a known helper that we can use instead of each-in, OR is there someone who can recommend me if we CAN create a new helper for this?

Ember.js - where to place server communication logic

I'm having a problem figuring out what is the idiomatic Ember.js way of representing the following task: the application should display a list of master entries (let's call them classes) each one having one or more child entries (let's call them students), the latter having in turn teacher-marks, as sub-child entries.
I want the page to display the list of classes along with the list of students for each one as the standard view, while the teacher-marks should be initially hidden, but made visible on demand, when they should be editable in place (new and remove operations).
The way I've implemented this display-wise is this:
Each class is displayed as an Ember view, as I need a lot of interaction with the controller. The teacher-marks are implemented as Ember components, as well as the students. Neither the view, nor the components perform any communication with the server, they basically just send actions to the controller / route.
Displaying and hiding the teacher-marks are done via properties in the components.
I only have one route for all this (and as far as Ember.js tutorials and examples go, I feel I may be doing it wrong) and one controller. The route is named 'classes' and has an ArrayController displaying the array of classes. I have item controllers for each class.
The route object is the one that fetches data from the server. The manipulated child elements (e.g. new/removed teacher-marks) are pushed to the server via dedicated model functions (using Ajax calls) called from the main route events. I am not using Ember data.
As far as I read, I should be having nested resources for this implementation, but am otherwise at a loss as to how to implement it that way and keep displaying the classes and students at all times.
I would greatly appreciate all amendments and suggestions to the way I currently implemented this. It would also help me a great deal if you could add why will something work better one way or the other.
I haven't included any code as I feel it would be better expressed this way as a problem. My code is obviously more complicated than above, and not involving the class - students case. If needed, I can sketch-up a model.

EmberJS view components and separate data store

I'm looking at creating a google maps component. But I would like it to be self contained so it will have its own model, controllers and views. So for example the component will fetch its own data from the server and I'll also be able to refresh the data when needed. Ideally I'd simply add the component to the current template that is showing, so for example: {{map-view}} and then everything the component needs to do will take care of its self.
The component will also need to listen to triggered events from other controllers as a user will be able to search for a specific location and the map will need to change its position.
Is this possible to do in EmberJS? As I haven't found anything like this, specially when having its own model. I know there is a component in EmberJS but it seems very limited. Am I wrong in thinking this?
the controller cannot have its own model all values must be passed to component. Please refer to ember docs and this Discussion
You can make a google map component and pass the location and marker data to the component. this data will get updated due to ember data binding.
so you can have something like this
{{map-view location=userEnteredValue}}
you can search for ember component talk by Kris Selden on youtube which includes a google map component good for you to start with.
updated
https://gist.github.com/krisselden/8189650