Angular elements bound to same function. Avoid multiple call on each digest - javascript

Given the following:
<div data-ng-repeat="val in vals">
<div data-ng-class:{'myClass':isEngineOn(val)}>
<span data-ng-show="isEngineOn(val)">yeah it's on</span>
<span data-ng-show="!isEngineOn(val)"> standby</span>
<button data-ng-disabled="isEngineOn(val)">Start engine</button>
<div>
</div>
isEngineOn changes with websocket messages I receive from the server.
Is there a way to avoid evaluating isEngineOn, 4 times during each digest, per each value in the repeat? Something like initializing a variable or something?

You can do that with simple CSS and without calling the function in the spans. I think thats much more efficient than a JavaScript solution, especially when you have a repeat over many elements because you can save bindings:
<div data-ng-repeat="val in vals">
<div data-ng-class:{'myClass':isEngineOn(val)}>
<span class="showWhenOn">yeah it's on</span>
<span class="showWhenOff"> standby</span>
<button onclick="alert('Starting...')">Start engine</button>
</div>
</div>
CSS:
.showWhenOn {
display: none;
}
.myClass .showWhenOn {
display: inline;
}
.myClass .showWhenOff {
display: none;
}
.myClass button {
pointer-events: none;
color: silver;
}
JS Fiddle

Yes, just have a variable in the controller that holds the result, and update that variable when you receive an update from the server:
In your controller:
$scope.engineOn = isEngineOn();//also make sure to update from server whenever you need
Note that if your isEngineOn() function is no longer called from the view it doesn't need to be on the scope, it can be declared as a regular variable.
HTML:
<div data-ng-class="{'myClass':engineOn}">
<span data-ng-show="engineOn">yeah it's on</span>
<span data-ng-show="!engineOn"> standby</span>
<div>
EDIT 2: The ng-init, as you said, did not update on digest so I've taken a second approach.
I've taken the long way round, and created a corresponding array for your values and you can read from that:
<div data-ng-repeat="val in vals" >
<div data-ng-class="{'myClass':enginOn[val]}">
<span data-ng-show="engineOn[val]">yeah it's on</span>
<span data-ng-show="!engineOn[val]"> standby</span>
<button data-ng-disabled="isEngineOn(val)">Start engine</button>
</div>
</div>
Fiddle.

You can set watcher to variable that changes when you receive answer from server, for example:
scope.$watch(function(){ return <var that changes>; }, function(oldv, newv){
if(oldv !== newv)
scope.isEngineOn = <Calculate here>;
});
Then use:
<span data-ng-show="isEngineOn">

Related

this.$ or this.$$ to select all elements with same id or class name - Polymer

I have 3 paper-toggle-buttons that I would like to have disabled until I click an "edit" button (makes sense to do that).
I have cobbled this together in a long-winded form, however I wanted to know if there was a way in PolymerJS that you could use either the this.$.ID-NAME or the this.$$('CLASS-NAME') to select all of the paper-toggle-buttons, assuming that I gave them all the same ID and CLASS names (bad practise to duplicate ID's I know).
Any help is appreciated. I know that it's currently working, but I just want to know if there's an easier way.
I am currently working with the following (the toggle will occur when clicking a button with on-click event "editMode"):
HTML
<div class="detail info horizontal layout">
<div class="bodyHeaderText flex">Active User</div>
<paper-toggle-button class="toggle" id="toggle" checked$="{{isActive}}" disabled></paper-toggle-button>
</div>
<div class="detail info horizontal layout">
<div class="bodyHeaderText flex">Operator</div>
<paper-toggle-button class="toggle" id="toggle" checked$="{{isOperator}}" disabled></paper-toggle-button>
</div>
<div class="detail info horizontal layout">
<div class="bodyHeaderText flex">Manager</div>
<paper-toggle-button class="toggle" id="toggle" checked$="{{isManager}}" disabled></paper-toggle-button>
</div>
PolymerJS
editMode : function() {
toggle1 = this.$.toggle1;
toggle2 = this.$.toggle2;
toggle3 = this.$.toggle3;
if( EditDiv.style['display'] == 'none' )
{
toggle1.toggleAttribute('disabled');
toggle2.toggleAttribute('disabled');
toggle3.toggleAttribute('disabled');
}
else
{
toggle1.toggleAttribute('disabled');
toggle2.toggleAttribute('disabled');
toggle3.toggleAttribute('disabled');
}
}
You could take a look to Polymer DOM API, there're a lof of functions to interact with the DOM. I think you're looking for Polymer.dom(this.root).querySelectorAll('.toggle')
$$ returns the first node in the local DOM that matches selector.
you can do
Array
.from(Polymer.dom(this.root).querySelectorAll('.foo'))
.forEach($0 => /* do something */)
;
Then, just a note, your snippet doesn't make much sense because you are performing the same operation in if and else statements:
if(expression) {
toggle1.toggleAttribute('disabled')
} else {
toggle1.toggleAttribute('disabled')
}
// is equal to:
toggle1.toggleAttribute('disabled')
your code could definitely look like:
{
editMode() {
return [
this.$.toggle1,
this.$.toggle2,
this.$.toggle3
]
.forEach($0 => $0.toggleAttribute('disabled'))
}
}

How to call a onClick javascript function using bootstrap buttons and inside a form?

I am not able to change the css properties of a div when calling the onClick function.
<h1 id="hello">hello</h1>
<div id="notification" class="alert alert-dismissible alert-success">
<button type="button" class="close" data-dismiss="alert">×</button>
<strong>Well done!</strong> You successfully posted to Facebook!
</div>
<div align="center" class="col-sm-4">
#using (Html.BeginForm("distShare", null, new { area = "" }))
{
<button onclick="facebookButton2()" class="btn btn-primary" type="submit">Share this to Facebook</button>
}
</div>
function facebookButton2() {
document.getElementById("notification").style.visibility = visible;
document.getElementById("notification").style.color = red;
document.getElementById("hello").style.color = red;
}
The "hello" was simply for testing purposes. I have tried using JQuery and the onSubmit function as well. The notification div starts off as visibility: hidden.
I guess that the values you are passing should be strings, I honestly doubt that you have declared javascript variables called visible and red anywhere in your page:
function facebookButton2() {
document.getElementById("notification").style.visibility = 'visible';
document.getElementById("notification").style.color = 'red';
document.getElementById("hello").style.color = 'red';
}
Change your function as:
function facebookButton2() {
document.getElementById("notification").setAttribute('style','visibility:visible');
document.getElementById("notification").setAttribute('style','color:red');
document.getElementById("hello").setAttribute('style','color:red');
}
See that working here: http://jsbin.com/rosubazuna/1/
Found the problem.
The "distShare" was calling the distShare() method in my controller and that method returned me to a "new" view even though it was the same page. I was essentially refreshing the page. So it was technically working and I just didn't realize it. However, I also did have to change the values to strings as Darin Dimitrov suggested. Thanks for your help!

find is not working to select data from dom in jquery

what i need
i need to access href from class events_links .
html code
<div class="row flush frt" itemscope="" itemtype="http://schema.org/Event">
<div class="12u">
<div class="evntblk">
<a itemprop="url" class="events_links" href="/dailymail-ideal-homeshow">
<h2 class="lnh1" itemprop="name">Ideal Home Show - London</h2>
</a>
<div style="display:block; float:right; width:auto; color:#7c7c7c;"></div>
<span itemprop="startDate" class="startdates" content="2015-03-20">20 Mar-06 Apr 2015</span><span itemprop="endDate" class="enddates" content="2015-04-06"></span><br><span itemprop="location" itemscope="" itemtype="http://schema.org/Place"><span itemprop="name" style="display:none">Olympia Exhibition Centre</span><span itemprop="address" itemscope="" itemtype="http://schema.org/PostalAddress"><span itemprop="addressLocality" class="eventcity">London</span>,
<span itemprop="addressCountry" class="eventcountry">UK</span></span></span>
<p class="tal" style="overflow:hidden">The ZEE Asian Pavilions are a celebration of British Asian Culture, that encapsulates Asian food, Asian fashion,...<br><span style="background: none repeat scroll 0 0 #ECECEC; border-radius: 5px; color: #333333; display: inline-block; font-size: 0.8em;line-height: 13px; margin: 5px 2px 0 0 !important; padding: 5px 8px;">Home Furnishings & Home Textiles</span></p>
</div>
<div class="row flush footer"><div class="12u"><a class="button button-blue small">View Details</a></div></div>
js code
$('.small').click(function()
{
alert("test");
window.location.href = $(this).find(".events_links").attr("href");
});
snapshot of html element
i have tried to access with .parent() but it not working.
o/p
i need to access events_links class by click on class small so that i
would get href from that html element.
any suggestion are most welcome.
Simple solution to get only the related url is with parent() function:
$('.small').click(function()
{
window.location.href = $(this).parent().parent().parent().find(".events_links").attr("href");
});
since you are three levels underneath.
find() will start searching from the given object downwards in hierarchy.
BUT as stated before, this will fail, as soon as you change your html layout and maybe drop or add a div container.
it would be much better practice to give your divs containing the urls unique id's or store the link with the data attribute of the button.
So for example if in your HTML Code you had this
<div id="link12" class="event_links" href="FOUND THIS!">
<div class="whatever">
<div class="anotherone">
<div class="button small" data-link="link12" data-href="FOUND THIS HERE TOO!">
CLICK HERE
</div>
</div>
</div>
</div>
Then your click code could access URL via 2 methods:
$('.small').click(function()
{
// METHOD 1: get by storing unique id with button
alert($('#'+$(this).attr('data-link')).attr("href"));
// METHOD 2: same effect, but shorter storing href at button
alert($(this).attr('data-href'));
});
try this
$('.small').click(function() {
alert("test");
window.location.href = $(".events_links").attr("href");
});
I would suggest data-attr in this case, where you do not want to depend on code structure and css.
<div class="row flush footer">
<div class="12u">
<a class="button button-blue small" data-relative-path="some-location">View Details</a>
</div>
</div>
And
$('.small').click(function(){
window.location.href = $(this).data('relative-path');
});
You can try this one:
$('.small').click(function() {
alert("test");
window.location.href = $(".evntblk .events_links").attr("href");
});
If you need to get only href of the single .event_links object in the current .box.panel do:
$('.small').click(function()
{
alert("test");
window.location.href = $(this).closest(".box.panel").find(".events_links").attr("href");
});
closest will get you the first parent element that matches the selector. This way if you have any other .event_links that are not into this panel, they'll be skipped. If you use parent() you'll be forced to keep the same HTML sturcture between the .small and it's parents.
First of all it's bad practice to try and load a url based on a css class. That is because it is probable you use css classes repeatedly on a single page, resulting in multiple anchor selections.
However you could do the following:
$('.small').click(function()
{
var btn = $(this);
// find the closest element of click button with class 'event-block'
// find the element with class 'events_links'
// change window location to value at href
window.location.href = btn.closest('.event-block').find('.events_links').attr("href");
});

Assign dynamic controller in ng-repeat

I am new to Angularjs. I've tried a example in here.
file index.html:
<div ng-repeat="data in ctl.dataList">
<div class="col-md-6">
<textarea type="text" ng-mouseover="ctl.mouseOverFunc()" ng-mouseleave="ctl.mouseLeaveFunc()">{{data.value}}</textarea>
<button ng-show="ctl.showCloseBtn">X</button>
</div>
</div>
file app.js:
app.controller('FocusController', function() {
this.showCloseBtn = false;
this.dataList = [{
value: "one"
}, {
value: "two"
}];
this.mouseOverFunc = function() {
this.showCloseBtn = true;
};
this.mouseLeaveFunc = function() {
this.showCloseBtn = false;
};
});
I want to show close button when mouse overed every textarea like facebook chat in this picture. But my issues is when mouse over one of textarea then all X button was showed.
How do i assign dynamic controller to every textarea or how to do like facebook chat ?
Thanks for your help
You can do with CSS as well as AngularJS. I suggest you to do with CSS which is Simple. And Do your ng-click on the button.
This Plunker Demo is using with CSS and added ng-click there. Please check the styles and classes added.
Styles
<style>
.field:hover .btn-close {
display:block;
}
.btn-close {
display:none;
}
</style>
HTML
<div ng-repeat="data in ctl.dataList">
<div class="col-md-7 field">
<textarea></textarea>
<button ng-click="doSomething()" class="btn-close">X</button>
</div>
</div>
This Plunker Demo is with AngilarJS as explained in the other answer by New Dev.
<div ng-repeat="data in ctl.dataList">
<div ng-mouseover="data.showX = true"
ng-mouseleave="data.showX = false">
<textarea></textarea>
<button ng-click="doSomething()" ng-show="data.showX">X</button>
</div>
Typically, it would be best to create a directive for this functionality and encapsulate all the logic of clicking the "x" button, but for simplicity you could also leverage the child scope created by ng-repeat, and do the following:
<div ng-repeat="data in ctl.dataList">
<div ng-mouseover="data.showX = true"
ng-mouseleave="data.showX = false">
<textarea type="text"></textarea>
<button ng-show="data.showX" ng-click="ctl.close(data)">X</button>
</div>
</div>
ng-repeat="item in items" creates a child scope for each item, so you can set values on the child scope.
Here's your modified plunker
EDIT:
As suggested in the comments, if you have nothing more complex than showing or hiding the button, definitely CSS approach is the simplest way to go. Use the above example then as an illustration for how scopes work.

How to find the div have the particular class

html:
<tr>
<td class="last_msg" id="408"><a href="/index/408" id="408">
<div id="div408" class="msg-div">
<div class="msg-actions">
<div id="unr_msg408" class="msg-unread"></div>
</div>
<div style="margin-top:14px; margin-bottom: 14px; line-height: 21px;">
<span class="msg-sender-name">Name</span>
<span class="msg-date">Date</span><br>
</div>
</div>
</a>
<span class="msg_dlt_icon"><img id="dlt408" src="/public/images/icon-delete-blue.png" class="msg_icon_dlt" onclick="return deleteMessage()"></span>
</td>
</tr>
On clicking the span with class msg_dlt_icon,i need to check whether the div with class msg-actions have the div <div id="unr_msg408" class="msg-unread"></div>.
I tried the below line,
var unread =$(this).closest("tr").find('.msg-actions').hasClass('.msg-unread');
I alerted the unread variable,it always return false.
I want to find whether <div id="unr_msg408" class="msg-unread"></div> is present inside <div class="msg-actions"> .
Is it possible to do.
So you need to first find the children of .msg-actions, then check whether it has the class msg-unread.
var unread =$(this).closest("tr").find('.msg-actions > div ').hasClass('msg-unread');
you could use
var unread = $(this).closest('tr').find('.msg-actions .msg-unread').length;
This
.hasClass('.msg-unread')
is incorrect. hasClass already implies that you're looking for a CSS class. You're trying to treat it as a call like $('.msg-unread'). Your hasClass() is telling jquery to literally looking for an element that looks like
<foo class=".msg-unread">
^---note this .
The call should be just
.hasClass('msg-unread')
WITHOUT the ..

Categories

Resources