Say I have a few links in my navigation:
...
{{#linkTo 'projects.trending' tagName="li"}}
<a href="#" {{bindAttr href="view.href"}}> Trending projects</a>
{{/linkTo}}
{{#linkTo 'projects.all' tagName="li"}}
<a href="#" {{bindAttr href="view.href"}}> All projects</a>
{{/linkTo}}
...
When I click one of these links, it will fetch data via Ajax and go to that route. But sometimes it takes a while to fetch the data, so I'd like to show a spinner. I currently already have a global spinner at the top of the page. It would be cool to show a spinner next to the navigation link that was clicked, so the user sees what page is currently loading.
What would be the best/easiest approach to implement this?
You could put a span next to each navigation link that's hidden by default, and contains the spinner. Then onClick, show the span. Hide all of them after ajax is done.
Related
I have multiple tabs in my page which link to some internal routes. When an user clicks on a tab ,the route has to be rendered and also the tab has to be highlighted but once in a few clicks the highlighting does not shift to the new tab and the old tab remains highlighted but the route of the clicked tab gets rendered.
The highlighting is done by an action inside the li tag and the #link-to is nested inside the li tag.
In my investigation till now what I have found is that the when this happens the click event is not registered. I get a bunch of mouse events but no click event. Seems like the click event is eaten up.
<ul class="nav nav-tabs">
{{# each tab in tabBars}}
<li {{action 'someAction'}}>{{#link-to tab.link}}{{/link-to}}</li>
{{/each}}
</ul>
The action should be triggered all times when a tab is click and the new tab should be highlighted.
Try to do something like this instead:
{{#link-to tab.link tagName='li'}}click me{{/link-to}}
(and omit the <li> tag).
Then you can check for the active class to highlight the li element.
The {{link-to}} helper renders a link which will get an additional class="active" if the link matches the current route. You can then style this by CSS.
See https://guides.emberjs.com/v1.10.0/templates/links/ and search for "active".
Other options
Since the {{link-to}} will trigger the tab.link route's beforeModel hook, perhaps this is the place you might want to set view-related properties to be "data-downed" to the <li>. I would personally reserve this hook for business logic.
When I absolutely need to fire an action before transitioning (usually, this is when I want to fire something like a tracking event), I use the invokeAction closure action which comes with the ember-link-action addon although it looks like might only support 1.13.13
{{link-to invokeAction=(action "someAction")}}
Best practice
For the action in the <li> element you generally want to avoid setting actions on non-interactive elements since it creates an accessibility concern for users of assistive technology (see no-invalid-interactive).
However, this doesn't mean you should turn the <li> element into an interactive element by doing something link <li role="button"> as this violates more a11y concerns (see no-nested-interactive).
I found a solution which does not involve actions:
<ul class="nav nav-tabs">
{{#each tab in tabs}}
{{#link-to tab.link id=tab.id tagName='li' }}<a>{{tab.title}}</a>{{/link-to}}
{{/each}}
</ul>
link-to masquerading as li and having a dummy anchor inside it.
I started with learning EmberJS and maybe the answer is trivial, but after some researching, I still can't find a solution.
In my model template, I have some buttons(each for the different object) which after click should expand sidebar with its details.
What do I want to reach is something like this:
Could someone provide me with some simple twiddle?
There are two ways to achieve this effect.
Using controller's variable
{{#foreach model as |obj|}}
<button onclick={{action (mut activeModel) obj}}>{{obj.name}}</button>
{{/foreach}}
<!--Somewhere later in template-->
{{#if activeModel}}
<!--Code of overlay and sidebar, close button sets activeModel to undefined-->
{{/if}}
Using child (nested) route
Parent template:
{{#foreach model as |obj|}}
{{#link-to 'parentRoute.childRoute' obj tagName="button"}}
{{obj.name}}
{{/link-to}}
{{/foreach}}
<!--Somewhere later in template-->
{{outlet}}
Child template should contain code of overlay and sidebar, close button redirects back to parent route
well, one of the options is that you can create components and pass the modified model(modify the model using onclick function) as the data to that component.
for example,
let us just say that this is your main template
<button onclick="changeSideBar()">click</button>
<div style="display:none; //render it in the left-half(using bootstrap models)">
{{sidebar-component model=model.modified}}
</div>
in the javascript code (component.js),
function changeSideBar()
{
var modified= ;//set as per your convienince by iterating actual models or by any means
this.set('model.modified',modified);
//make display of sidebar div "block"
}
sidebar-component is your component. make the component as per your wish.
hope it helps.
I can't help much without your templates or codes. It would be great if you provide some of your works.
When I add new list items to an existing dropdown button they do not show up on the front end. The dropdown just continues to show the original list items. All my caching systems are off and I cleared the cache locally, but I'm still getting the same issue. Anyone know what could be causing this?
<div class="sidebar-dropdown">
<button data-dropdown="drop" aria-controls="drop", aria-expanded="false" class="large alert round button dropdown">Select Type</button>
<br>
<ul id="drop" data-dropdown-content class="f-dropdown" role="menu" aria-hidden="false" tabindex="-1">
<li>All-Purpose (USA)</li>
<li>Mobile</li>
<li>E-Commerce</li>
<li>All-Purpose (CAN)</li>
<li>Tablet POS</li>
<li>High Risk</li>
</ul>
</div>
The Foundation-generated dropdown needs to be refreshed when new content is added to it. This can be done by adding this to your javascript, which adds a listener to the dropdown element(s):
$(document).foundation('dropdown', 'reflow');
See the docs for more info
The jsfiddle.
From the posts#index template, I can create a new comment by using the #linkTo helper which goes to the PostNewComment Route and renders the post/newcomment form. If I click save the newly created comment is persisted using the 'save event' inside the PostNewComment Route.
You can uncomment the line below in post/comments" template, to see it working
{{#linkTo "post.newComment"}} Add comment{{/linkTo}}
I changed my UI to use a controller isAddingNew button and the render helper to determine When to display the form and now if I click the save button, I get:
Uncaught TypeError: Cannot call method 'one' of null
This how I render it:
<p> {{render "post.newComment" }} </p>
I suspect it is a scope issue because the error is only triggered when 'save' is clicked after using the render helper.
To reach the 'add new comment' button:
click -> post -> a post title -> click comments link -> add comment
Is there a way to make the 'Post/newComment form' displayed via the 'render helper' in the post/comments template to use the 'save event' defined in the PostNewComment Route.
Right now clicking on the 'save button' which is defined in that form goes directly to the parent route ie PostCommentsRoute instead of going to its own route probably because I displaying the form via the render helper.
I thought calling 'save' should go to its own controller and then bubble to its own route where it is actually defined, before attempting to bubble up the hierarchy to the PostComments Route.
There's probably a few alternatives, but this works and is pretty idiomatic: http://jsfiddle.net/GabSY/4/
In particular:
{{#if model}}
<form {{action save content on='submit'}}>
{{view Ember.TextArea valueBinding="content.body" placeholder="body"}}
<button type="submit"> save comment </button>
<button {{action cancel}}> Cancel</button>
</form>
{{else}}
<button {{action open}}> Add comment </button>
{{/if}}
The reason you were getting the Uncaught TypeError: Cannot call method 'one' of null error was that the PostNewCommentController's model was never set. What I ended up doing was using the open action on the PostNewCommentController to set the model of the controller, which can be used in a Handlebars {{if}} to determine whether the form should be displayed or not.
I prefer this approach to the alternative of setting content/model (they are aliases to each other) of the PostNewCommentController from within the PostCommentsRoute's setupController method because if you go down that route, it's easy to start mixing concerns between not-very-related controllers and routes. In my approach, all the logic for setting the content/model of the new comment takes place in the controller for new comments, which makes sense since a new comment no longer has its own route to initialize this data.
(Note: I am using Ember version 1.0.0-rc.3)
I'm trying to catch the 'click' of a {{linkTo}} using a view, so that I can do additional stuff (basically scroll the list of users in the sidebar) besides merely loading the new template. Me being relatively new to this (but having read the documentation!), I thought the following would just work:
"users" template:
{{#each user in users}}
{{#view App.ClickView}}
{{#linkTo user user}}{{ user.name }}{{/linkTo}}
{{/view}}
{{/each}}
the view code:
App.ClickView = Ember.View.extend({
click: function(evt) {
// do stuff
}
});
and for context, the layout template:
<div id='sidebar'>
{{#each user in users}}
{{#linkTo user user}}{{ user.name }}{{/linkTo}}
{{/each}}
</div>
<div id='main'>
{{ outlet }}
</div>
Referring back to the users template, you can see that each {{linkTo}} is contained within a view. I'm expecting for a click on that {{linkTo}} to therefore bubble up to, and caught by the view (App.ClickView). Unfortunately, it doesn't. It seems like the click is somehow not being bubbled up to the view when it's happens on a {{linkTo}}... What should I do?
Note #1:
If I replace the {{linkTo}} (only in div#main! I don't intend to replace the ones in div#sidebar) with an <a> element, it works, and the click gets caught by the view. However, I'm not so sure that i want to go down this route (I'd have to replicate the functionality of the {{linkTo}}!). And I'm thinking that there ought to be a better way to do this. Is there?
Note #2:
*Note that I'm also aware that i can put my intended "do stuff" code in renderTemplate() of the UserRoute, but the problem with that is that the effect will happen for every link to that route (including the ones in the sidebar - which is not what I want). I want the scroll to only trigger for specific {{linkTo}}s - specifically the {{linkTo}}s in div#main.
I would suggest using an anchor (<a>) tag with {{action ... target="view"}} in it instead of linkTo, apply your conditional logic in the view, and then if appropriate, re-send to the controller (this.get('controller').send(actionName), let it bubble to the router, and do a transitionTo in a router event handler.