`active` class not switching based on `route` update - ember.js

on load of new route the active class not switching to new tab. I am not able to find the solution for this.
but the new page is loading without any issue. the only issue is the active class not switching to new page and not remove from the old page.
how to fix this?
here is my hbs file :
<div class="navbar-sub-header navbar-sub-header---tab-bar" style="border:1px solid red;">
<div class="rdc-tab-bar">
{{#link-to "auth-page.credit-card.credit-cardno" class="rdc-tab-bar___tab"}}
Credit Card //by default active added
{{/link-to}}
{{#link-to "auth-page.i-banking" class="rdc-tab-bar___tab"}}
Online Baning //when click page loads, active not swithing
{{/link-to}}
</div>
</div>
my router.js :
this.route('auth-page', function() {
this.route('credit-card', function() {
this.route('credit-cardno');
this.route('credit-otp'); //works fine
});
this.route('i-banking'); //not updating to active state
});
UDATE
When I directly hit the url as : http://localhost:4302/auth-page/i-banking I am getting active class updated.

Related

How to save the endpoint data in model store if call is made from actions in controller

I have created a dialog box using the ember-modal-dialog. The content that is going to displayed in the dialog is received from the server. I am able to make the call to server and fetch the data. But I don't know how to save the data into my model store from actions.
Controller.js
actions:{
fiModal1: function(photo){
Ember.$('body').addClass('centered-modal-showing');
var currentState = this;
photo.toggleProperty('fidialogShowing'))
console.log('opendialog');
raw({
url: 'http://example.co.in/api/photo/'+photo.get('like_pk')+'/likes/',
type: 'GET',
}).then(function(result){
currentState.set('model.feed.liker',result)
});
},
bookmarked:function(liker){
liker.set('is_bookmarked',true)
},
}
feed.hbs
<p {{action "fiModal" photo }}>
{{photo.0.numlikes}}
</p>
{{#if photo.fidialogShowing}}
{{#modal-dialog translucentOverlay=true close = (action "fiDialogClose" photo)}}
{{#each model.feed.liker as |liker}}
<div class = "col-sm-6">
{{#if liker.is_bookmarked}}
<a href {{action "unbookmarked" liker}}>
<img class="foll" src = "images/button-bookmark-secondary-state-dark-b-g.png">
</a>
{{else}}
<a href {{action "bookmarked" liker}}>
<img class="foll" src = "images/button-bookmark.png">
</a>
{{/if}}
</div>
{{/each}}
Now the problem is that when action inside the dialog box is fired it throws an error:
fiver.set is not function
I think that the problem is occurring because I am not saving the result in the model store. How should I do it so the action inside the dialog box also works?
You can just encapsulate the results from your server into Ember.Object
Ember.Object.create(json)
For exemple replace your line
currentState.set('model.feed.liker',result)
by
currentState.set('model.feed.liker', result.map(function(item) {
return Ember.Object.create(item);
})
that way each elements inside your model.feed.liker should have a method 'set' available.

Reacting to a controller/view initialization event

As you can see in this jsbin, I am trying to do the following:
Load some data. Data is loaded from a FIXTURE, slowly, because we have a high latency in the FIXTURE.
While the data is being loaded, I want to show some simple text: Loading ...
Once the data is received, show an outlet with the real data.
I have tried with controllers.nodesIndex.isUpdating, isLoading, isUpdated .isLoaded, and several other variations, but this is not working. How can I react to a "data is ready" event?
EDIT
I have also tried with a property binding dataLoaded; in the route, when the data is received, I manually update the property. But this is also not working. I am getting several error messages:
Uncaught Error: Something you did caused a view to re-render after it rendered but before it was inserted into the DOM.
Assertion failed: Emptying a view in the inBuffer state is not allowed and should not happen under normal circumstances. Most likely there is a bug in your application. This may be due to excessive property change notifications
Uncaught Error: You cannot modify child views while in the inBuffer state
This is the template:
<div id="legend" class="">
<legend class="">Nodes <span class="badge">{{controllers.nodesIndex.length}} records</span></legend>
</div>
<!-- Just to get visual feedback when the data gets loaded -->
{{outlet}}
{{#if controllers.nodesIndex.dataLoaded}}
<!-- This should only be shown when the data is ready -->
{{outlet}}
{{else}}
Loading ...
{{/if}}
</fieldset>
</form>
</article>
This is the controller:
App.NodesIndexController = Ember.ArrayController.extend({
dataLoadedBinding: 'App.nodesLoaded'
});
And this is the route:
App.NodesIndexRoute = Ember.Route.extend({
model: function() {
return App.Node.find().then(function(data) {
console.log('Data received > data=%o', data);
App.set('nodesLoaded', true);
return data;
});
}
});
The canonical way to provide alternate markup in handlebars for content that is loading appears to be isUpdating property of a controller's content.
{{#if content.isUpdating}}
{{!-- content markup here --}}
{{else}}
{{!-- Loading message here --}}
{{/if}}

Ember.js not sideloading

I have the need to load random items in my Ember application. To do this, I do the following:
Test.ApplicationRoute = Ember.Route.extend({
events: {
randomItem: function() {
var route = this;
$.getJSON('item/random.json', function(data) {
Test.Item.find(data).then(function(item) {
route.transitionTo('items.show', item);
});
});
}, // ..... etc
This works fine, except for one thing: nested-sideloaded data is not shown. When items.show is visited via a {{#linkTo 'items.show' item}}, the item's child data is also loaded and visible. However, when this randomItem event is fired, only the direct children are shown. The children of the children are not.
Why is this and/or how do I fix this?
It turns out, the reason the artifacts are not being shown is that I try to listen to controller.content.isLoaded to adapt the view to show a loading image if the content is still loading.
For some reason, the following shows the loading... text and icon forever on subsequent usages of the route:
{{#if controller.model.isLoaded}}
<div class="row">
</div>
{{#each artifact in controller}}
{{render "artifacts.show" artifact}}
{{else}}
<span class="muted">There are no artifacts.</span>
{{/each}}
{{else}}
<i class="icon-spin icon-spinner icon-large"></i> Loading...
{{/if}}
If anyone knows why, please let me know, so I can solve this problem.

Persisting object controller details

I have the following template setup displaying a list of items, and wrapping each list in its own controller:
{{#each controller itemController="contact"}}
<div class="contact-entry">
<div class="title" {{action toggle on="click"}}>{{title}}</div>
{{#if showDetails}}
<div class="details">
<div>{{safe details}}</div>
</div>
{{/if}}
</div>
{{/each}}
The main controller is an ArrayController called ContentsController, and each item is wrapped in an ObjectController called ContentController. The content of the ContentsController is set explicitly in the route (I've simplified the data):
App.ContactsRoute = Em.Route.extend({
model: function() {
return [{'title': 'first'}, {'title': 'second'}];
}
});
This works really well. However if I navigate to another path and then back again, the settings on the ContentController don't persist. What happens is that the model data gets reloaded, and I assume a ObjectController gets created for each of the list items. Incidentally this is not the case for the ContentsController, which keeps its settings.
What is the solution to preventing ember of creating new ContentController for every list item every time I access the page?
I'm assuming your reference to ContentController is really ContactsController since you are using itemController="contact" in your #each block.
What kind of data are you trying to persist? The showDetails flag? The ContactControllers are going be created and destroyed anytime you exit / enter the route and there isn't anyway I know of to keep those around.
The ContactsController keeps its properties because its a singleton controller generated because you have a ContactsRoute.

Ember.js: Complex view layout, what's the proper approach?

We're building app that allows users to post messages to various social media outlets. Our designer has created a series of interactions which allow users to change various settings in their application by use of sliding panels. I've done a quick screen cap to illustrate:
http://screencast.com/t/tDlyMud7Yb7e
The question I have is one of architecture. I'm not sure whether I should be using a View or a Controller (or both) to store some of the methods these panels will contain. Here's the HTML for the panels. They're not currently in a script tag or view:
<div id="panel-account-settings" class="panel closed">
<div class="panel-inner">
<i class="icon-cancel"></i>close
<h3>Account Settings</h3>
Google Analytics
Link Shortening
Disconnect Account
</div>
<div id="panel-google-analytics" class="panel-inner">
<i class="icon-arrow-right"></i>back
<h3>Google Analytics</h3>
<div class="toggle">
<label>Off</label>
</div>
<p>We <strong>won't</strong> append stuff to your links, so they <strong>won't</strong> be trackable in your Google Analytics account.</p>
<img src="{{ STATIC_URL }}images/ga-addressbar.png" />
</div>
<div id="panel-disconnect" class="panel-inner">
<i class="icon-arrow-right"></i>back
<h3>Disconnect This Account</h3>
<p>If you disconnect this account you will lose all the metrics we tracked for each message. Are you absolute sure you want to get rid of them?</p>
<div class="button-group">
Disconnect
</div>
</div>
</div>
The gear icon shown in the video is contained with the accounts template
<script type="text/x-handlebars" data-template-name="accounts">
{{#each account in controller}}
<div class="avatar-name">
<p>{{account.name}}</p>
<p>#{{account.username}}</p>
<i class="icon-cog" {{action "openPanel" Social.SettingsView account }}></i>
</div>
{{/each}}
</script>
which has a bare bones controller
Social.AccountsController = Ember.ArrayController.extend({
openPanel: function(view,account){
console.log(view,account);
$(this).parents(".item-account").addClass("active");
$("#panel-account-settings").prepareTransition().removeClass("closed");
}
});
as well as a Route and a Model. Given the interaction I'm looking to accomplish, my question is where should I be putting the pieces and parts? At a minimum I need to pass in the current Account model so that I know which account I'll be applying changes to. I thought about creating a mainPanel view which would contain the other view...something like this:
<script type="text/x-handlebars" data-template-name="panelView">
<div id="panel-account-settings" class="panel closed">
{{ partial "panelSettingsView" }}
{{ partial "panelAnalyticsView" }}
{{ partial "panelDisconnectView" }}
</div>
</script>
and then the action helper on the gear icon could pass in the account AND the required view. But I'm not sure if that's the right approach. I'd appreciate some input or suggestions. Thanks.
UPDATE 1
Ideally I'd like to eventually load in the content of each panel via AJAX but that's a want to, not a need to.
UPDATE 2
I tried creating a PanelView which would contain the logic on which panels to load:
Social.PanelView = Ember.View.extend({
tagName: 'div',
classNames: ['panel-inner'],
openPanel: function(view,account){
console.log(view,account);
}
});
But when I tried to call it from the gear icon I got an error. This:
<i class="icon-cog" {{action openPanel target="Social.PanelView" }}></i>
Threw this error:
Uncaught Error: assertion failed: The action 'openPanel' did not exist on Social.PanelView
Isn't that the correct syntax?
UPDATE 3
Adding version information:
DEBUG: Ember.VERSION : 1.0.0-rc.1
DEBUG: Handlebars.VERSION : 1.0.0-rc.3
DEBUG: jQuery.VERSION : 1.9.1
The best practice is to always put any DOM- or UI-related logic into your view, and leave data representation to the controller (i.e., a reference to a 'selected' item in the controller is a common example).
Your Social.AccountsController.openPanel method has logic that touches the DOM, which is entirely a view concern. A good start would be to move that logic into the view (Social. SettingsView ?).
It'd be a bit easier to understand your goals and offer more suggestions if you had a jsfiddle of what you have so far.
EDIT: Another good practice is to decompose things into very small objects. So you could explore having a selectedAccount ObjectController whose content is the currently chosen Account (and a corresponding View for it).