ember rollback attributes when user cancel the edit action - ember.js

I have an app in which user can edit a product and make some changes. When user clicks the edit button, then it opens up a dialog. User can go through multiple windows and do some changes. After which, user can click save or cancel the edit action. In case of cancelling the action, I want to rollback the dirty attributes. I am using below code to do the same but somehow, some of the changes do get rollbacked while other don't. Can anyone point out if their is an issue? (below is my code for reference)
cancelAction() {
if (this.get('isEditMode') && this.get('model').get('hasDirtyAttributes')) {
this.get('model').send('becomeInvalid');
this.get('model').rollBackAttributes();
}

I suggest following approach:
Make a copy of model each time before opening a modal
When user makes change, work with copy
If user clicks "save", update original model and persist it.
If user clicks "cancel", no action needed.
This allows to worry less about reverting attributes and provides better user experience.

There is a good addon for managing changes on ember-data model:
ember-data-change-tracker.
Currently ember-data don't track changes in object, json, custom types.
Ember-data-change-tracker support these types.

Related

ember.js beginner advice required

I am attempting to learn ember.js to produce a simple-ish web application. I have read around the subject and completed the basic tutorial on emberjs.com . So far, I have managed to create the beginnings of an API using PHP and I have been able to retrieve that data into my fledgling application. So far so good.
As a starter, I wish to retrieve a list of users from the server and populate a select with these values. The select is to sit on the menu bar and the selection from this drives the rest of the data for the application. I have placed the model in models/users.js. The application menu I have defined in templates/application.hbs (not sure if this is considered correct or not).
I am unable to get the users data for the select retrieved from the server unless I visit the users route that I have also setup. How can I ensure that the users data is populated at application initialisation? How would I apply/filter the rest of the application data upon selection from this component - would I need to set a global variable or something?
Additionally, I am using materializecss, which requires $('select').material_select(); to be run in order to render the select input. I have this as:
$( document ).ready(function(){
$('select').material_select();
});
in templates/route.js and works fine on initial page load, but upon navigation to another area and back again, the select is not rendered, and from what I have read, I need to call material_select() again, but I can't for the life of me work out where this call should go.
If anyone is willing to take the time to help me better understand things, I will be very grateful.
Cheers
Tim
Preloading Clarification
I wish to have a select box on the main menu bar (menu-bar component). The user will use this to select a user. All content in the app will be filtered to the currently selected user. I currently have an API endpoint (/users.php) which returns the required data, but I am only able to get my application to call this when I visit the users route, which obviously I won't be doing when the app loads initially. So I am thinking I need to preload the data somehow, unless there is a better way that I am not aware of?
Create a component for menu and put the component in application.hbs
And in component put the materialize stuff like this : (notice to the place)
//components/menu-bar.js
didInsertElement(){
this._super(...arguments);
Ember.$( document ).ready(function(){
Ember.$('select').material_select();
});
}
And
//templates/application.hbs
{{menu-bar}}
{{outlet}}
UPDATE
Create a service holding current user selection and use it in other places that you want be changed by changing the user selection.
These codes is just for showing that the solution for what you want (changing the other parts of app based on changing the selected user in menu) is services.
//services/current-selection.js
...
selectedUser: null,
...
and
//components/menu-bar.js
currentSelection: Ember.inject.service(),
actions: {
selectUser(user){
this.set('currentSelection.selectedUser', user);
}
}
and in another place you want to be notified when selection changed :
//components/user-info.js
currentSelection: Ember.inject.service(),
and corresponding template
//templates/components/user-info.hbs
{{#if currentSelection.selectedUser}}
<span>Current Username: <strong>{{currentSelection.selectedUser}}</strong></span>
{{/if}}
Update For pre-loading users
Actually it's not pre-loading
In menu-bar component you load a select box and populate it by calling a service to backend. If you put this component in application.hbs you could ensure what you want is satisfied.
//components/menu-bar.js
store: Ember.inject.store(),
users: Ember.computed(function(){
return this.get('store').findAll('user');
}),
OR
In application route model hook you fetch those users and pass to component like {{menu-bar users=model}}
And for these two options you can use users in menu-bar template.
But pay attention to that if the users count is a lot, this is very bad for performance or UX. If your users are a lot it's better to use from a autocomplete component

Updating CPropertyPage on tab selection

I am looking for the best way to update a CPropertyPage once it is clicked. Currently, my pages receive it's information during OnInitDialog(). However, when the user does something on page one, it can effect what is on page two.
The only solution I can think to use is an "Update" button. Once the button is clicked, the page refreshes its information by calling the same functions that take place during OnInitDialog(). Is there an event that occurs when the user clicks on a different CPropertyPage of a CPropertySheet?
Using an "Update" button is poor design because it requires the user to force the update. Instead, you should look to maintain the state of the values that could cause the update. This can be done in a structure or class object that can then be made accessible to CPropertyPage::OnSetActive of the page that needs the updated values. OnSetActive is called just before the page is to be made the active one. It's your opportunity to update values on the page before it displays.

Rolling back an unsaved record? Cancelling an edit of a record should revert to its state prior to the edit, not to the blank state

In my app, i let the user create a record on clientside and fiddle with it prior to saving. The record is of a pretty complex model with a lot of realtionships. To edit the record, a modal dialog opens and displays a form.
Example scenario:
You've created a new record on client side. It's in the blank state.
Then you proceed to edit the record. You make changes to the form in the modal dialog and press OK. The record now is in state A.
Then you proceed to edit the record again, turning the record to state B. But this time you mess the form up and decide to Cancel.
When you hit Cancel, the record should revert to state A.
The problem is that this is an unsaved record and thus record.rollback() can not be used.
All i could think of is making a copy of a record and feeding it to the form. But most of the form's fields are bound to related records, thus, you'd have to clone the record's related records recursively. This is a huge hack that i don't want to go for.
Any simpler suggestions?
The approach I have used is based on the buffered proxy pattern within my controllers.
This way your controller can just throw away the buffer on cancel or apply the buffer to models and orchestrate model saves when the user OKs the changes.
Here is an ember package you can use to get started:
https://www.npmjs.com/package/ember-buffered-proxy

Emberjs: Prevent back button from moving into another state

When a state describes a view rendered in a modal/popup, we ideally want the user to only navigate away from it through offered options i.e Save or Cancel buttons.
The back button presents a real issue when you design your application with states in mind and you use modals to render views in certain states (New, Edit ...).
Is there a way to hack into the states history to prevent, when desired, landing in a state through the back button.

Ember.js adding and removing views from the DOM?

I am looking into ember.js, after working with SproutCore 1 previously. I am looking for some examples on how to add and remove views from the DOM as the user navigates the application.
For instance, I have an application that contains a set of cases and each case has a workflow. There are also administration pages, etc.
When the user starts up the app, a dashboard-like user interface is shown. From here the user is able to search or click on a case in order to bring up that case. At this point I want to do the following:
I want to remove the GUI for the Dashboard, and i want to show the GUI for the case - which is a complex GUI in itself with its own set of navigation rules etc.
Also, within the case I want to add and remove portions of the GUI as the user navigates and manipulates the case.
When the user clicks on the "Dashboard" link, I want the current GUI to be removed, and the dashboard to be added again.
As this will be a somewhat large application I am not sure if toggling the isVisible parameter is sufficient, or if other measures needs to be taken in order to not overload the user's browser.
Is there a guide, or an example that shows how to do this ?
WARNING: OUTDATED ANSWER
A view inherits from Ember.View which means it gets some key methods. append(), which appends to body, appendTo(arg) which takes an argument and remove().
The argument is a jQuery style selector of where to insert the element in the DOM.
// my view
App.PartsView = Ember.View.extend({
...
});
// create/insert my view
App.partsView = App.PartsView.create();
App.partsView.appendTo('#partcontainer');
In my code I have a <div id="partcontainer"></div>.
// remove from DOM
App.partsView.remove();
The documentation has a good part on Building a View Hierarchy and later a section on Ember.ContainerView depending on whether you want to do it all programatically or not.