Ember-js Onclick function not work - ember.js

Im used Bootstrap v4-alpha Im added pop over its working, but i need to add popover-content for the on click function its not fire in Ember-js,
how to put onclick function in emebr-js
this is im used onlick event
<li class="list-group-item" onclick={{action `'event'}}>Airport Pickup</li>
This is my code sample
add-newbooking.hbs
<div class="form-group">
<a href="#" data-toggle="popover" data-placement="bottom" data-toggle="popover" title="Bill Category">
<input type="text" class="form-control" id="formGroupExampleInput" placeholder=""></a>
</div>
<title>Bootstrap Example</title>
<!-- loaded popover content -->
<div id="popover-content" style="display: none">
<ul class="list-group custom-popover">
<li class="list-group-item" onclick={{action 'event'}}>Airport Pickup</li>
<li class="list-group-item" >Food and Beverage</li>
<li class="list-group-item">Yoga Class</li>
</ul>
</div>
<script>$(document).ready(function() {
$('[data-toggle="popover"]').popover({
html: true,
content: function() {
return $('#popover-content').html();
}
});
});</script>
add-newbooking.js
import Ember from 'ember';
export default Ember.Component.extend({
actions:{
event: function () {
console.log("ppessssssss")
}
}
});

The guides have a whole section on this
<li class="list-group-item" {{action 'event'}}>Airport Pickup</li>
You could be better off adding a link or button inside the list item though so that the button is focusable etc

adding onclick and action on an element will add both events i.e. DOM events as well as ember events. so always remember to add any one of the events (preferably ember).

Related

Ember 2 - Hide / show content component

I have a component app/components/offer-listing.js:
import Ember from 'ember';
export default Ember.Component.extend({
isOfferShowing: false,
actions: {
offerShow() {
if (this.get('isOfferShowing')) {
this.set('isOfferShowing', false);
} else {
this.set('isOfferShowing', true);
}
}
}
});
and his template app/templates/components/offer-listing.hbs:
<div class="offer__container">
<div class="row">
<div class="gr-3">
<div class="offer__avatar" style="background-image: url('{{ offer.avatar }}')"></div>
</div>
<div class="gr-9">
<div class="offer__name" {{action "offerShow"}}>{{ offer.firstname }} {{ offer.lastname }}</div>
<div class="offer__age" {{action "offerShow"}}>{{ offer.age }} ans</div>
{{#if isOfferShowing}}
<div class="offer__description" {{action "offerShow"}}>{{offer.description}}</div>
{{else}}
<div class="offer__description" {{action "offerShow"}}>{{word-limit offer.description 50}}</div>
{{/if}}
{{#if isOfferShowing}}
<div class="+spacer"></div>
<a class="offer__button"><i class="fa fa-envelope"></i> Contacter par email</a>
<a class="offer__button"><i class="fa fa-phone"></i> Voir le numéro de téléphone</a>
{{/if}}
</div>
</div>
</div>
which is rendered in app/templates/index.hbs:
{{#each model as |offerUnit|}}
{{offer-listing offer=offerUnit}}
{{/each}}
The example is working great, however I would like to hide every "more" content when a new one is showing.
A working solution for this is available here : Using Ember component's methods inside template
Basically, either you keep a reference to the selected element in your controller and pass it to each of your offer-listing components. This way they could compare themselves with this reference to known if they need to be displayed or not.
Or you set a flag in each of your offer model depending on whether is needs to be displayed or not.

Template for modal from remote page

I am implementing modals as an ember component and I was wondering if and how could this be accomplished: If the content of the modal is coming from a different page, how would it be rendered as a template:
Example:
http://jsfiddle.net/koala_dev/NUCgp/918/
The script above opens a modal with this content:
http://fiddle.jshell.net/bHmRB/51/show/
But what if I wanted some extra data that depends on specific users, coming from the routes model? How would I insert something like
{{#each link in links}}
{{#link-to 'link.url'}}{{link.title}}{{/link-to}}
{{/each}}
into the remote page, so it would be rendered as a template, and not regular text?
Here is a very quick and easy example just to give you a right direction. You can play with it and parse the html to extract content (which is not relevant to the question).
You can setup a component for modal element. I've setup a component property (attribute) contentURL where you can set the url of the content.
Component handlebars
Notice the {{content}} which we used later in the action to save the ajax result. Action showModal is added on the link to execute the ajax call.
<script type="text/x-handlebars" id="components/bootstrap-modal">
<a data-toggle="modal" data-target="#myModal" {{action "showModal"}}>Click me !</a>
<!-- Modal -->
<div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h4 class="modal-title">Modal title</h4>
</div>
<div class="modal-body">{{content}}</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
<button type="button" class="btn btn-primary">Save changes</button>
</div>
</div>
<!-- /.modal-content -->
</div>
<!-- /.modal-dialog -->
</div>
<!-- /.modal -->
</script>
Component JS
App.BootstrapModalComponent = Ember.Component.extend({
/*initModal: function(){
}.on('didInsertElement'),*/
contentURL: null,
content: 'Content is loading...',
actions: {
showModal: function(){
var self = this;
var contentURL = this.get('contentURL');
if(contentURL == null){
this.set('content', '<p>No content url is given</p>');
}
console.log('get content from url > ' + contentURL);
$.ajax({
url: contentURL,
dataType: "html",
beforeSend: function(){console.log('before send');},
error: function(xhr, status, message){
console.log(message);
},
success: function (content) {
// parse and get the right html for the content
self.set('content', content);
}
});
}
}
});
Now you can call the component bootstrap-modal on your template like {{bootstrap-modal}}
For example:
<script type="text/x-handlebars" id="index">
{{bootstrap-modal contentURL="http://fiddle.jshell.net/bHmRB/51/show/"}}
</script>
jsFiddle example http://jsfiddle.net/sisir/NUCgp/1713/

Why didInsertElement hook trigger before elements rendered inside {{#each}} block?

I'm new to Ember, I want to add some query DOM manipulation code to the element in the {{#each}} block. So I google it up and found the solution from this guide:
views/products/index.js
import Spinner from 'appkit/utils/someJqueryCode';
Ember.View.reopen({
didInsertElement : function(){
this._super();
Ember.run.scheduleOnce('afterRender', this, this.afterRenderEvent);
},
afterRenderEvent : function(){
// implement this hook in your own subclasses and run your jQuery logic there
}
});
export default Ember.View.extend({
afterRenderEvent: function() {
Spinner();
}
});
templates/products/index.hbs
<div class='panel panel-default products'>
<div class='panel-heading'>
<h2 class='panel-title'>Our Prodcuts</h2>
</div>
<div class='panel-body'>
<ul class='row'>
{{#each}}
<li class='col-md-4'>
<div class='thumbnail'>
<img {{bind-attr src=url alt=alt}} />
</div>
<div class='caption'>
<h3 class='name-me'>{{name}}</h3>
<p>{{description}}</p>
<div class='row no-gutter'>
<div class='col-xs-3'>
<button class='btn btn-primary'>Buy</button>
</div>
</div>
</div>
</li>
{{/each}}
</li>
</div>
</div>
But I seems after the point when afterRenderEvent() is triggered, all the elements in the {{#each}} block hasn't been rendered to the DOM yet, thus, the jQuery code return undefined
What's the right way to do it?
Your view's didInsertElement hook will fire as soon as the application route is rendered, which happens before the index route. You might think that putting it in the index.js file will work, but it's going to just extend the default application view behavior.
You need to create a more focused view that lives within your index.hbs file. One that is only concerned with your spinner jQuery doohickey. That, and an each/else conditional could work nicely here. For example:
{{#each}}
{{#view App.SpinnerDoohickeyView}}
<li class='col-md-4'>
<div class='thumbnail'>
<img {{bind-attr src=url alt=alt}} />
</div>
<div class='caption'>
<h3 class='name-me'>{{name}}</h3>
<p>{{description}}</p>
<div class='row no-gutter'>
<div class='col-xs-3'>
<button class='btn btn-primary'>Buy</button>
</div>
</div>
</div>
</li>
{{/view}}
{{else}}
<li>Empty collection!</li>
{{/each}}
Notice that I've wrapped each list item in its own view. You could wrap the whole ul if you wanted... this is just an example. The idea is that you are only creating views when you have a model.
And now you can define the view, and simply use the didInsertElement hook to work with jQuery:
App.SpinnerDoohickeyView = Ember.View.extend({
didInsertElement: function () {
this.$('li').css('background', 'blue');
}
});
If you have a model to render, jQuery should be able to safely access it this way. Good luck!
Here's some further reading and some code from the Ember folks that looks like what I've shown you here: http://emberjs.com/guides/views/handling-events/

Change DIV class on click action Ember

I want to change the DIV class base on CLICK action. I am trying to make a floating sidebar like this http://startbootstrap.com/templates/simple-sidebar.html
This demo has only three lines of code for toggle-ing the class.
<script>
$("#menu-toggle").click(function(e) {
e.preventDefault();
$("#wrapper").toggleClass("active");
});
</script>
I want to achive same thing but in ember way. Below is my HTML code:
<div id="wrap">
<div class="pull-left" id="main_menu">
<ul class="list-group">
<li class="list-group-item">{{#link-to "selectImage"}}<h4>Choose Picture</h4>{{/link-to}}</li>
<li class="list-group-item">{{#link-to "message"}}<h4>Write Message</h4>{{/link-to}}</li>
<li class="list-group-item"><h4>Account info</h4></li>
<li class="list-group-item"><h4>Recent Orders</h4></li>
<li class="list-group-item"><h4>How to</h4></li>
<li class="list-group-item"><h4>FAQ</h4></li>
</ul>
</div>
<!-- Begin page content -->
<div class="container" id="page_content">
{{outlet}}
</div>
<!-- End page content -->
</div>
</script>
<script type="text/x-handlebars" id="cards/index">
<h1>
<button class="pull-left btn btn-default" data-target="#main_menu" {{action 'changeClass'}}>
<img src="images/icons/menu_tablet.png" class="main_menu"/>
</button>
</script>
Now I do not know how can I use the action to change the class in WRAP div. I will really appreciate any help regarding this issue.
You can add the action handler within the controller for cards/index
Controller = Ember.ObjectController.extend({
actions: {
changeClass: function() {
// Run logic here
}
}
})

In EmberJS my event triggers all the sub-views instead of just the targeted one

i'm learning EmberJS and building a comment section that allows 1 level of sub comments. I have an Ember View listing all the comments, when you click "reply" on a particular comment, it should display a textarea input for a user to write a sub-comment.
In my EmberJS code when you click "reply" it shows the textarea input for all the comments not just the specific one. Any advice would be appreciated :)
// View
App.commentsView = Em.View.create({
templateName: 'commentsTmpl',
showReply: false,
reply: function(e) {
e.view.set('showReply', true);
e.preventDefault();
}
});
App.replyCommentsView = Em.View.extend({
showReplyBinding: 'App.commentsView.showReply'
});
// Template
<script data-template-name="commentsTmpl" type="text/x-handlebars">
</h2>comment</h2>
{{#each App.commentsController}}
<div class="comment-group clearfix">
<div class="comment">
<img class="comment-pic" {{bindAttr src="userPic"}} alt="user pic">
<div class="comment-content">
{{userName}}
<span class="comment-body">{{text}}</span>
<div class="comment-actions clearfix">
<a href="#" {{action "reply"}}>Reply</a>
</div>
</div>
</div>
{{#view App.replyCommentsView}}
{{#if showReply}}
<div class="comment-reply">
<h2>sub-comment</h2>
<textarea class="txt-comment-reply" rows="2" cols="65"></textarea>
</div>
{{/if}}
{{/view}}
</div>
{{/each}}
</script>
Currently you are binding the showReply to App.commentsView which is the whole container. To be make it easy activate single comments, I'd suggest looking into a CollectionView, this way each of your comments will have their own view and you can toggle showReply on an individual comment's view.
Something like this: (Sorry, I haven't tested it)
App.commentsView = Em.View.create({
templateName: 'commentsTmpl'
});
App.CommentView = Em.View.extend({
classNames: "comment-group clearfix".w(),
showReply: false,
reply: function(e) {
e.preventDefault()
this.set("showReply", true)
}
})
// Template
<script data-template-name="commentsTmpl" type="text/x-handlebars">
</h2>comment</h2>
{{#collection contentBinding="App.commentsController" itemViewClass="App.CommentView"}}
<div class="comment">
<img class="comment-pic" {{bindAttr src="content.userPic"}} alt="user pic">
<div class="comment-content">
{{content.userName}}
<span class="comment-body">{{content.text}}</span>
<div class="comment-actions clearfix">
<a href="#" {{action "reply"}}>Reply</a>
</div>
</div>
</div>
{{#if showReply}}
<div class="comment-reply">
<h2>sub-comment</h2>
<textarea class="txt-comment-reply" rows="2" cols="65"></textarea>
</div>
{{/if}}
{{/each}}
</script>