I am trying to hide an object using the jQuery method hide(), but it doesn't work.
I used console.log() to check the value of the argument in called function, so I know Im not doing right. But, i dont know how to make it work...
Here's what I have:
#------------------------Model------------------------
App.Monster = Ember.Object.extend({
name: "",
hp: 0,
isDead : false,
isDeadChanged: function(target, value){
App.monstersController.kill(target);
}.observes('isDead')
});
#------------------------Controller------------------------
App.monstersController = Ember.ArrayProxy.create({
content:[],
createMonster: function(name,hp){
var monster = App.Monster.create({name:name});
this.pushObject(monster);
},
kill: function(target){
//I Want the selected object to hide by using Jquery hide method!!
$('target').hide();
this.removeObject(target);
},
#------------------------HTML FILE------------------------
{{#each App.monstersController contentBinding="App.monstersController.content" tagName="ul"}}
<li>
{{view Ember.Checkbox checkedBinding="isDead"}}
<label for="" {{bindAttr class="isDead"}}>{{name}}</label>
</li>
{{/each}}
Generally bringing your DOM scripting patterns to Ember isn't going work, since Ember isn't about DOM manipulation it's about describing your application using objects. The DOM representation of your application will update automatically to reflect the state of its underlying data objects.
Ember.View tracks its visibility (and the visibility of its child views) with the isVisible property and will handle toggling the it's DOM representation for you. You should try to uncover the semantic object meaning of visibility for a given view context. For example, if you decided finished items in a todo list shouldn't be visible, you'd do:
{{#each item in controller}}
{{view App.TodoItemView isVisibileBinding="item.isComplete"}} <a {{action kill item}}>Done!</a>
{{/each}}
Don't quote target.
kill: function(target){
//I Want the selected object to hide by using Jquery hide method!!
$(target).hide();
this.removeObject(target);
},
$('target') looks for <target> elements.
Related
I have few knockout attributes that are not associated with model. Rather i am assigning rank to every list element(incremental list +1). Now i want to use this rank1 element in child tags.
But i realize that i can't do it directly since its not coming from Model (example IsPremium below).
So I am finding closest element that has this rank1 attribute to find its value. I feel this is not optimized way since it will look up everytime.
Can i somehow bind this attribute to child elements as well?
Below is the code.
<script type="text/html" id="listingTemp">
<li data-bind='attr: {rank1 : $.getRank(IsPremium), isPremium : IsPremium}>
<div class="stock-detail">
..few other nested elements
<a class="slideShow" data-bind="attr: { isPremium : IsPremium} onclick="$.triggerSearchListingsTracking($(this).attr('isPremium '),$(this).closest('.listingContent').attr('rank1')
I am creating an unordered list in an Ember.js view by using the each helper. I also have some Javascript that runs on the didInsertElement hook, which selects each list item. However, that selector fails to select any elements if I generate the list using the each helper. Any thoughts on how to get results from the selector?
relevant view:
<script type="text/x-handlebars" data-template-name="slider">
<ul>
{{#each slide in controller}}
<li><img src="./resource/locations/1/test.jpg"></li>
{{/each}}
</ul>
<br>
</script>
relevant JS:
App.SliderView = Ember.View.extend({
templateName: "slider",
didInsertElement: function() {
var self = this;
var items = $(">ul>li", self.$());
//...
}
});
Update:
I believe the problem arises because I am loading the models that populate my controller asynchronously. Is there any way to listen to the event that occurs when the model is first populated?
My Model Code:
App.Location = DS.Model.extend({
thenSlider: DS.hasMany("slide", {async: true})
});
App.Slide = DS.Model.extend({
//...
});
Looks good to me, you're probably facing a problem where your data is populating after didInsertElement has fired. didInsertElement only fires when Slider has been inserted initially, not necessarily when the elements inside of it are inserted/modified.
http://emberjs.jsbin.com/liluxece/1/edit
Since it's async, I'd use render and hook it up to another view, that way you can use didInsertElement on a case by case situation for each item.
{{render 'template' context}}
Here's an example
http://emberjs.jsbin.com/liluxece/5/edit
I'm looking for a more succint and possibly more jQuery-e way of doing the following.
I have an object lbl which is a div. Contained within the div is a span tag that is the firstName and lastName property of the lbl object. So, so far we have the following HTML:
<div class="label">
<span class="firstName">John</span>
<span class="lastName">Doe</span>
</div>
Now consider the following fiddle http://jsfiddle.net/VfErV/
$('#btnSubmit').click(function ()
{
var lbl = $('<div>').addClass('label');
//I need to be able to access the child elements of the parent div
//via the dot operator
firstName = $('<span>').text('test1').addClass('firstName');
lastName = $('<span>').text('test2').addClass('lastName');
lbl.append(firstName);
lbl.append(lastName);
lbl.firstName = firstName;
lbl.lastName = lastName;
$('#page').append(lbl);
console.log(lbl.firstName.text());
//span tag is never added to the div
var lbl2 = $('<div>').addClass('label');
lbl2.firstName = $('<span>').text('test2').addClass('firstName');
$('#page').append(lbl2);
});
Please refer to the fiddle for behavior. I need to be able to control font-sizes, borders, etc. on the child objects of the parent div container, lbl, and have the appear on the page as normal DOM elements. All of the JS up until the first lbl control is appended to the page works. This looks clunky to me, though. Is there a better way to have child elements of a DOM element be properties of the parent object more easily/succintly?
You asked for a more jQuery-way to do this. Here's how you could create your structure:
$('#btnSubmit').click(function () {
var lbl = $('<div>').addClass('label');
lbl.html('<span class="firstName">test1</span><span class="lastName">test2</span>');
$('#page').append(lbl);
// Then, to retrieve that data, you can just do something like this
console.log(lbl.find(".firstName").text());
});
Then, anytime you want to get the firstName from a given label div, you just use .find("firstName") to get that object and then get its text.
Best practices generally just use the structure of the DOM and find things as needed in the DOM rather than make new duplicate ways to access everything. For 99% of what we do, accessing things through the DOM is plenty fast and doesn't require creation and duplication of another way to get to the data. And, jQuery makes it pretty easy to find things in the DOM as long as you have enough id or class markers to identify what you're looking for (which you do).
Here's a fiddle for this question (make sure you have your console open):
Basically, I have a handlebars block view as a parent, then loop through an array of items and create child block views for each item. Later, those children are modified in some way, and I want to detect and handle that event.
Summary Code:
{{#view App.outerView}}
{{#each item in items}}
<h6>Person:</h6>
{{#view App.innerView}}
<dl>
<dt>First Name</dt><dd>{{item.first}}</dd>
<dt>Last Name</dt><dd>{{item.last}}</dd>
</dl>
{{/view}}
{{/each}}
{{/view}}
At some later point:
controller.get( 'items' ).pushObject( 'new item' );
In the jsFiddle, I am trying to keep the last child object always highlighted (active = true). When the outerView is initially inserted, we apply the highlight to the last item and it works as expected. Later, when we add a new item, our highlight method fires, but it doesn't see the new item.
2 Questions about this:
Main Question: Why doesn't the last item (Matt) get highlighted? In other words, why, after a new item has been added, does childViews.length still report the old value? Is there a better way to be doing this?
Secondary Question: Why does the observer on childViews fire twice when we add the new item? (3 times total: 1 on initial insert, 2 from addition of 1 new child item)
Edit: I've adjusted the fiddle a little to better illustrate my needs. Notice the mixed content of the outerView (HTML + innerViews). Basically, my outerView needs to accept ANY content as children, not just an array/collection of views/data.
Edit 2: Further clarification: Manipulating those child views after the fact is a different story and can be accomplished either by working with the contents of childViews (ember views) or using jQuery to manipulate HTML elements that may not be a formal ember view object, or any other means. The real goal here is simply to capture the event when ANY of the outerView content changes (with a current copy of childViews).
Edit 3: Here's an Issue on Github
You initial code looks a little tangled up. Here is a better way to achieve the same result:
http://jsfiddle.net/XaN8T/1/
You should wrap each item in a controller, which is easily done with the {{each}} helper:
<script data-template-name="application" type="text/x-handlebars">
This is a list:
<ul>
{{each controller itemController="item" itemViewClass="App.ItemView"}}
</ul>
</script>
And create a separate template for your items:
<script data-template-name="item" type="text/x-handlebars">
<h6>Person:</h6>
<div {{bindAttr class=":content active"}}>
<dl>
<dt>First Name</dt><dd>{{first}}</dd>
<dt>Last Name</dt><dd>{{last}}</dd>
</dl>
</div>
</script>
Then you can take advantage of needs and computed properties in Ember with the active property:
App.ItemController = Ember.ObjectController.extend({
needs: ['application'], //This way each ItemController can access the ApplicationController's content (i.e. the list of all items)
active: function() {
return this.get('controllers.application.lastObject') === this.get('content');
}.property('controllers.application.lastObject')
});
The App.ItemView then binds its css class to the controller's active property:
App.ItemView = Ember.View.extend({
tagName: 'li',
templateName: 'item',
classNameBindings: ['controller.active']
});
Voila! It works :)
A better way of doing what you have accomplished in the fiddle is by the use of Ember.CollectionView
and then adding a computed property which determines whether the child is the last one or not on the itemViewClass for the active class
active: function () {
return this.get("elementId") === this.get("parentView.childViews.lastObject.elementId");
}.property('parentView.childViews.length'),
Here is a Working Fiddle
Note Whenever there is a need to deal with collection of views either use CollectionView or Ember.ContainerView(This gives much more control over the child views manipulation) as per your requirements, but for most of the cases Ember.CollectionView would suffice
I want something like below
Edit Selected Menu
selectionMenu is a variable in ResAdmin.adminController Ember Object.
In order to declare a binding for an attribute, you'll need to use bindAttr. You can use this helper to bind an attribute either to a global path or to a variable in the current context, such as your view.
For instance, you might have a template like this:
<a {{bindAttr href="menuUrl"}}>Edit Selected Menu</a>
Which is bound to a property in your view, like this:
App.MyView = Ember.View.extend({
menuUrl: function() {
return "/Admin/MenuEdit/" + this.get("App.adminController.selectionMenu");
}.property("App.adminController.selectionMenu)
});
I created a fiddle for this example.