I have a angularJS function which returns a value and would like to create an if statement in javascript. I've tried the following but so far no luck.
AngularJS:
$scope.orderTotal = function(index) {
var orderTotal = 0;
angular.forEach($localStorage.items, function(items) {
orderTotal += items.quantity;
})
return orderTotal;
};
Javascriptfile.js:
jQuery(document).ready(function() {
document.write(orderTotal());
}
or:
if (orderTotal() > 10) {
document.write(orderTotal());
}
Is it possible to do something like this and what would it look like?
RvdM - "Because adding and removing classes on divs is something I do with javascript I need to have some variables defined in angularjs available in javascript. Are there better ways to accomplish this?"
Yes, to add and remove classes on elements in AngularJS, use the ng-class directive.
From the Docs:
ngClass
The ngClass directive allows you to dynamically set CSS classes on an HTML element by databinding an expression that represents all classes to be added.
-- AngularJS ng-class Directive API Reference.
You can - I'd question why, but oh well. You can use angular.element and .scope to get the current scope your function is contained in.
For example, say your above function was inside the controller MyController
<div id="controller" ng-controller="MyController"></div>
The JS you'd use is:
var scope = angular.element(document.getElementById("controller")).scope();
scope now has access to all scope methods:
var total = scope.orderTotal();
the DOM :
<div id="mycontroller" ng-controller="mycontroller"></div>
In jquery you do this and it will access that controller and call that function
var orderTotal;
$('#mycontroller').load = function(){
orderTotal = angular.element('#mycontroller').scope().orderTotal();
}
If a "complete" callback is provided, it is executed after post-processing and HTML insertion has been performed
Here you go :)
Related
I'm trying to bind a text input to an attribute within a directive, the reason being I don't want to have to introduce a controller each time I add a new directive of this type. Is this even possible or do you always have to specify a controller when using ng-model. Code example is worth a thousand words so please take a look at http://codepen.io/scottwio/pen/HKqiw . As you type in the input the amount should change.
There are two issues with your code:
scope.$watch(attrs.amount, function (v) {...}); <=>
scope.$watch('100', function (v) {...});
which is never going to change, so does not do what you want.
Since the elements attribute is never going to change, function draw(aniTime) { var amount = attrs.amount; is not so usefull.
You can fix them like this:
scope.$watch('amount', function (v) {...});
and
function draw(aniTime) {
var amount = scope.amount;
...
See, also, this short demo.
If you want to share the specified amount with the parent scope, then you need to set up a two-way data-binding and specify a property in the parent scope to bind to. E.g.:
// Parent scope
$scope.someAmount = 100;
// In HTML
<custommarc amount="someAmount" ...
// In directive
scope: {
amount: '='
...
I know a DIV can be attached to a Javascript variable with code like this:
var targetDiv = jQuery('#targetDiv');
However, I am looking for a way to attach ALL the DIVs or ones of a certain class to Javascript variables.
So, if I have the following elements:
<div id='bozo'>
<div id='ranger'>
<div id='smokey'>
I will end up with the variables:
bozo
ranger
smokey
I've been building lots of jQuery apps and they often have many divs that need to be kept track of in my code. I want to find an easier way to get control of these divs than assigning them to variables at the beginning of my app.
Either a jQuery or Javascript solution would be fine.
The most effective way would be to use a JavaScript object.
var divs = {};
$("div").each(function() {
if ($(this).attr('id') !== undefined) {
divs[$(this).attr('id')] = $(this);
}
});
With your current HTML, the divs could then be accessed like so:
divs["bozo"].show(0);
divs["ranger"]show(0);
divs["smokey"].show(0);
You can't name the JavaScript variables directly after the div IDs, because they have different naming conventions. For example, test-div is a valid ID for an HTML element, but not for a JavaScript variable.
However, if an ID just so happens to be a valid JavaScript variable name, then it can be accessed as a mnemonic property of the object:
divs.bozo.show(0);
divs.ranger.hide(0);
See this demo.
Edit: Added functionality to detect when the div has no ID, based on suggestions from icktoofay and ABFORCE.
I think there is no need to assign every jQuery object to a javascript variable/object. Because the jQuery syntax is very very easy to use.
You can refer to a html element so easy with jQuery, like this:
$("div") // all div elements
$("div#foo") // div with id="foo"
$(".foo") // all element which have 'foo' class
However if your want to assign to a JS object use this:
var obj = new Object() // or = {};
$("div[id]").each(function(){
obj[$(this).attr("id")] = $(this);
});
You can "...access those variables without executing any code, as browsers put elements with an id attribute into the global scope on their own." According to Blender's findings in the comment below. So one can access those variables by the div's IDs as demonstrated here:
http://jsfiddle.net/xhWwH/2
EDIT: Kept my previous answer for reference purpose.
Although I do not agree with this type of programming (very unsafe!!!!). I believe this is what you are looking for: http://jsfiddle.net/haoudoin/xhWwH/
$("div").each(function(index) {
console.log(this.id);
eval("" +this.id + "=this;");
});
console.log("creates: " + bozo);
console.log("creates: " + ranger);
console.log("creates: " + smokey);
// reference to your div
alert(bozo.id);;
I come from a Rails background and am attempting to use AngularJS with Rails. I am stuck on a very simple thing: how does one construct what rails calls 'virtual attributes' in an Angularjs environment? Let me give an example.
I have a rails model, called Medication, and it has two attributes, dosage and count. I want to have a 'total' virtual attribute that returns dosage * count. This is trivial in Rails, since it is just an instance method of class Medication.
So, how does that map into the AngularJS world?
Clarification: I am using an ng-repeat directive on Medications (plural) for which I have a MedicationsController. For each ng-repeat loop, I get a 'medication' object, where I want to apply this 'instance method'
total = function() { return dosage * count }
How is that coded? Where do I put the function?
It is really simple with AngularJS as you can use any JavaScript function in AngularJS view. So just define a function on your object (or directly on a scope). For example, give a controller like this:
var MedicationCtrl = function($scope) {
$scope.medication = {
dosage : 0.5,
count : 10,
total : function() {
return this.dosage * this.count;
}
};
}
You can simply write:
Total: {{medication.total()}}
Here is a jsFiddle: http://jsfiddle.net/4r5g5/1/
Then, if you've got a collection of items and don't want to put any logic on an object level, you can define this method on a controller like so:
var MedicationCtrl = function($scope) {
$scope.total = function(medication) {
return medication.dosage * medication.count;
};
};
and use this function from a markup like follows:
<ul ng-repeat="m in medications" ng-controller="MedicationCtrl">
<li>{{m.dosage}} + {{m.count}} = {{total(m)}}</li>
</ul>
And the above code in the jsFiddle: http://jsfiddle.net/4r5g5/3/
Let's say I'm generating markup through server-side code. I'm generating a bunch of HTML tags but I want to add custom client-side behavior.
With JavaScript (if I had a reference to the DOM node) I could have written:
var myDOMNode = ...
myDOMNode.myCustomAttribute = "Hi!";
Now the issue here is that I don't want to qualify every element with an unique id just to initialize data. And it's really strange to me, that there's not an easier and unobtrusive way to attach client-side behavior.
If I'm remembing this correctly, this is valid IE stuff.
<div onload="this.myCustomAttribute='Hi!'"></div>
If I was able to do this, I should be able to access it's "data context" though the identifier 'myCustomAttribute', which is really what I want.
The following will work but not validate:
<div myattribute="myvalue"></div>
But if you are injecting it into the HTML with Javascript, then perhaps that's not concern for you. Otherwise, you can use something like jQuery to process the elements before adding them to the DOM:
$(elements).each(function(){
$(this).attr('myattribute','myvalue');
});
First off you should access custom attributes using the getAttribute and setAttribute methods if you want your code to work on other browsers than IE.
As to your event handler question that really depends on how you add the event handler.
Assigning a function directly to the elements onXXXX property would allow you access the the element via this.
If you use IE's attachEvent you can't use this, you can access the element that generated the event using event.srcElementbut that may be child element of the div. Hence you will need to test for the existance of myCustomAttribute and search up the ancestors until you find it.
I do appricate the input but I've finally figured this out and it's the way I go about initialization that has been the thorn in my side.
What you never wan't do is to pollute your global namespace with a bunch of short lived identifiers. Any time you put id="" on an element you're doing exactly that (same thing for any top level function). By relying on jQuery, HTML5 data and CSS there's a solution to my problem which I think is quite elegant.
What I do is that I reserve a CSS class for a specific behavior and then use HTML5 data to parameterize the behavior. When the document is ready, I query the document (using Query) for the CSS class that represents the behavior and initialize the client-side behavior.
I've been doing a lot of ASP.NET and within this context both the id="" and name="" belongs to ASP.NET and is pretty useless for anything else than internal ASP.NET stuff. What you typically find yourself doing is to get at a server-side property called ClientID you can refer to this from client-side JavaScript, it's a lot of hassle. They made it easier in 4.0 but fundamentally I think it's pretty much broken.
Using this hybrid of CSS, HTML5 data and jQuery solves this problem altogether. Here's an example of an attached behavior that uses regular expressions to validate the input of a textbox.
<input type="text" class="-input-regex" data-regex="^[a-z]+$" />
And here's the script:
$(function () {
function checkRegex(inp) {
if (inp.data("regex").test(inp.val()))
inp.data("good-value", inp.val());
else
inp.val(inp.data("good-value"));
}
$(".-input-regex")
.each(function () {
// starting with jQuery 1.5
// you can get at HTML5 data like this
var inp = $(this);
var pattern = inp.data("regex");
inp.data("regex", new RegExp(pattern));
checkRegex(inp);
})
.keyup(function (e) {
checkRegex($(this));
})
.change(function (e) {
checkRegex($(this));
})
.bind("paste", undefined, function (e) {
checkRegex($(this));
})
;
});
Totally clean, no funky id="" or obtrusive dependency.
In HTML5 there are HTML5 data attributes introduced exactly for the case.
<!DOCTYPE html>
<div data-my-custom-attribute='Hi!'></div>
is now corect, validating html. You can use any name starting with data- in any quantity.
There is jQuery .data method for interaction with them. Use .data( key ) to get, .data(key, value) to set data-key attribute. For example,
$('div').each(function () {
$(this).html($(this).data('myCustomAttribute')).data('processed', 'OK');
});
How about this?
<script>
function LoadElement(myDiv)
{
alert(this.myCustomAttribute);
}
</script>
<div onload="LoadElement(this)"></div>
not tested btw
Since you're trying to do this for multiple elements, you may try name attributes and getElementsByName.
<div name="handleonload">...</div>
window.onload = function () {
var divs = document.getElementsByName('handleonload');
for (var i = 0; i < divs.length; i += 1) {
divs[i].foo = 'bar';
}
};
Alternatively, you can use selectors, using libraries (such as jQuery and Prototype) and their respective iterators. This will also allow for you to search by other attributes (such as class).
Though, be cautious with your terminology:
obj.property = value;
<tag attribute="value">
<div style="width:100px;height:100px;border:solid black 1px" myCustomAttribute='Hi!' onclick="alert(myCustomAttribute);"></div>
The onload event is used for server side events. Its not part of the standard html element events.
Take a look at the following functions (especially the walk_the_dom one):
// walk_the_DOM visits every node of the tree in HTML source order, starting
// from some given node. It invokes a function,
// passing it each node in turn. walk_the_DOM calls
// itself to process each of the child nodes.
var walk_the_DOM = function walk(node, func) {
func(node);
node = node.firstChild;
while (node) {
walk(node, func);
node = node.nextSibling;
}
};
// getElementsByAttribute takes an attribute name string and an optional
// matching value. It calls walk_the_DOM, passing it a
// function that looks for an attribute name in the
// node. The matching nodes are accumulated in a
// results array.
var getElementsByAttribute = function (att, value) {
var results = [];
walk_the_DOM(document.body, function (node) {
var actual = node.nodeType === 1 && node.getAttribute(att);
if (typeof actual === 'string' &&
(actual === value || typeof value !== 'string')) {
results.push(node);
}
});
return results;
};
With the above two functions at hand, now we can do something like this:
some link
<script>
var els = getElementsByAttribute('dreas');
if (els.length > 0) {
els[0].innerHTML = 'changed text';
}
</script>
Notice how now I am making finding that particular element (which has an attribute called dreas) without using an id or a class name...or even a tag name
Looks like jQuery is the best bet for this one based on my searching. You can bind an object to a DOM node by:
var domNode = ...
var myObject = { ... }
$(domNode).data('mydata', mymyObj);
then you can call the data back up the same way, using your key.
var myObect = $(domNode).data('mydata');
I assume you could also store a reference to this within this object, but that may be more info then you really want. Hope I could help.
HI All,
I have a piece of javaScript that removes commas from a provided string (in my case currency values)
It is:
function replaceCommaInCurrency(myField, val)
{
var re = /,/g;
document.net1003Form.myField.value=val.replace(re, '');
}
'MyField' was my attempt to dynamically have this work on any field that I pass in, but it doesn't work, I get errors saying 'MyField' is not valid. I sort of get my, but I thought this was valid.
I am calling by using: onBlur="replaceCommaInCurrency(this.name, this.value);return false;"
this.name and this.value are passing in the right values...field name and its value.
How do I do this dynamically?
-Jason
You can use eval to make your code snippet work:
eval("document.net1003Form." + myField + ".value=val.replace(re, '');");
As mentioned below, the square brackets work (and don't suck like eval), stupid me for forgetting about those:
document.net1003Form[myField].value=val.replace(re, '');
Alternatively, try something like this:
function replaceCommaInCurrency(field){
var re = /,/g;
field.value = field.value.replace(re, '');
}
Which gets called like so:
onBlur="replaceCommaInCurrency(this); return false";
You should consider using a javascript toolkit for things like this. You could set a class like "currency" on each input, then use this snippet of jQuery based Javascript to handle everything:
$(function(){
$("input.currency").bind('blur', function(){
this.value = $(this).val().replace(',', '');
})
});
This code would fire on document ready, attach an event handler to each input with currency as its class, and then do the replacements. Note that you don't need a regex for replacement as well.
If you code it right into the markup like that, e.g. onblur="replaceCommaInCurrency(this)", the control originating the event gets passed as the parameter. Then you should be able to do something like:
myField.value = myField.value.replace(re, '');
with jQuery:
var jqField = $(myField);
jqField.val(jqField.val().replace(re, ''));
In general, you should be using a framework that will handle low level functionality like this, but the specific answer to your question is to use bracket notation for the field name:
function replaceCommaInCurrency( myField, val)
{
var re = /,/g;
document.net1003Form[myField].value=val.replace(re, '');
}
function removeCommaInCurrency(myField)
{
var re = /,/g;
myField.value=myField.value.replace(re, '');
}
-- and then call it like this:
<input type="text" name="..." onchange="removeCommaInCurrency(this);">
flatline and roenving's solution with ‘this’ is the cleaner approach, it also avoids the problems of ‘document.formname.fieldname’.
(Use ‘document.forms.formname’ to access a form without possible clashing on forms having the same name as members of the document object, and ‘forms.elements.fieldname’ to do the same with fields. Like all JavaScript object, object[namevariable] can also be used. Or, better, add IDs and use the unambiguous document.getElementById method.)
By moving binding into the script you can also remove the inline JavaScript of the onclick attribute, making the markup cleaner still:
<input type="text" class="number" name="something" />
...
<script type="text/javascript"> // external script is best, linked after all forms
function numberfield_bind() {
var inputs= document.getElementsByTagName('input');
for (var inputi= inputs.length; inputi-->0;)
if (inputs[inputi].className=='number')
inputs[inputi].onchange= numberfield_change;
}
function numberfield_change() {
this.value= this.value.split(',').join('');
}
numberfield_bind();
</script>