angularjs call a function - javascript

I am using angular js. How can i call a function if the length of the input text id greater than 5.
<input class="form-control" style="width:230px" ngmodel="Lookupemployer" ng-if={{ }} />
I want to call the below function
$scope.get = function()
{
}
if the length of the Lookupemployer is greater than 5.
I tried like this
ng-if={{ Lookupemployer.length >5 ? get() : ""}}
but did not work. Can anyone help me
Thanks,

The ng-if directive is used to determine whether or not to create the element in the DOM. It is not an actual conditional statement to be used to execute code.
Read the documentation for ng-if for further details: https://docs.angularjs.org/api/ng/directive/ngIf
You want to use ng-change. Call a method in that and have the function do the actual checking of the input length.
See the docs for more info: https://docs.angularjs.org/api/ng/directive/ngChange

First, you need to use ng-change - it will execute an expression on every change in the bound model.
You could do this all from the View, like so:
<input ng-model="foo" ng-change="foo.length > 5 && get()">
But it's better and cleaner to keep the logic out of the View (unless you consider it to be View-specific).
$scope.getIfNeeded = function(){
if ($scope.foo.length > 5) get();
}
And the View:
<input ng-model="foo" ng-change="getIfNeeded()">

Related

Angular ngClass is not updating my classes even though my condition change as expected

I have something like this in a template I am creating
<div ui-view id="app" class="nng-3" ng-class="{ 'app-mobile': app.isMobile, 'app-navbar-fixed': app.layout.isNavbarFixed, 'app-sidebar-fixed': app.layout.isSidebarFixed, 'app-sidebar-closed': app.layout.isSidebarClosed, 'app-footer-fixed': app.layout.isFooterFixed }"></div>
The values app.layout.isNavbarFixed, etc are initialized with either zero or one, and for the first time the page loads the appropriate classes are inserted into my div. Any change after that though, by means of a button that sets those values, is not reflected on my class attributes by ng-class.
If I directly print those variables in my template, eg. {{app.layout.isSidebarFixed}} I can see them changing from true to false and vice versa, but ng-class will not update or remove any new classes.
I am not sure where to begin and look for the solution for this since with my limited knowledge I cant spot any obvious mistake immediately. Does anyone have any idea on what causes this issue?
A workaround of mine is to manipulate a model variable just for the ng-class toggling:
1) Whenever my list is empty, I update my model:
$scope.extract = function(removeItemId) {
$scope.list= jQuery.grep($scope.list, function(item){return item.id != removeItemId});
if (!$scope.list.length) {
$scope.liststate = "empty";
}
}
2) Whenever my list is not empty, I set another state
$scope.extract = function(item) {
$scope.list.push(item);
$scope.liststate = "notempty";
}
3) I use this additional model on my ng-class:
ng-class="{'bg-empty': liststate == 'empty', 'bg-notempty': liststate == 'notempty'}"
Update*: Also you can add any other states if needed and use at ng-class like:
ng-class="{'bg-empty': liststate == 'empty', 'bg-notempty': liststate == 'notempty', 'bg-additional-state', liststate == 'additional-state'}"
Because you know, an initially empty list state is not equal with a list which is emptied by command.
Probably the ng-class implementation is not considering "0" to be "false" as you expect, because it's doing an strict comparision with ===.
Try expressing the conditions like this:
ng-class="{ 'app-mobile': app.isMobile == 0, 'app-navbar-fixed': app.layout.isNavbarFixed == 0, ...
Tried your variant. Have everything working. Please, check if your button click event is on $scope and AngularJS knows, that values changed.
For example, if function triggered by native DOM Event (some jQuery table updated or something) than you should use $apply function, to reflect changes on scope. Something like this:
$scope.eventHandler = function(e) {
$scope.$apply(function(){ $scope.someProp = e.value;}
}
In the mean time, check this jsfiddle
Update:
Please check this jsfiddle out. This works in AngularJS 1.4.8, but doesn't in other, that support jsfiddle. From what I know, it's not really a best idea to do an assignment inside of expression, the controller is meant for this thing.

Modifying scope object values in checkbox using ngchange

Forgive if this is a newbie error but I think this must be really simple and I am obviously missing something..
I have the following ngrepeat:
<div class="panel-body" data-ng-repeat="participant in activity.Participants" ng-show="showp" ng-init="participant.CheckInTime ='not set'"> <--The 'init' is for debug
{{getparticipantName(participant.ParticipantID)}}
Check in = {{participant.CheckInTime}}
<input type="checkbox" ng-model="participant.CheckedIn"
ng-change="setToNowOrNull(participant.CheckedIn, 'participant.CheckInTime')">
<br />
Check in = {{participant.CheckInTime}}
</div>
Which is nested within another ng-repeat which defines the controller etc. and that works fine. But when I click the checkbox, the settoNowOrNull function gets called, changes the value as it should, but this isn't returned to the participant.CheckInTime .. here is the function:
$scope.setToNowOrNull = function (deciderbool, thingtoset) {
if (deciderbool) //its been set to true.
{
$scope[thingtoset] = Date.now();
}
else //its been cleared to false
{
$scope[thingtoset] == null;
}
}
I added the $scope[thingtoset] after reading another question on here but to no avail.. the same with the single quotes around 'participant.CheckInTime' in the ng-change line. (This is supposed to pass the object not the value?)..
I'm obviously not getting something, and I'd have thought I could have done it in the html angular anyway rather than needing to call the controller for something so trivial - I just need to record the Date.Now() into the participant.CheckInTime. Thoughts anyone?
You can try this:
<input type="checkbox" ng-model="participant.CheckedIn"
ng-change="setToNowOrNull(participant)">
$scope.setToNowOrNull = function (participant) {
if (participant.CheckedIn) //its been set to true.
{
participant.CheckInTime = Date.now();
}
else //its been cleared to false
{
participant.CheckInTime == null;
}
}
There are several problems with your approach, particularly with
$scope[thingtoset] = Date.now();
Using value being passed into function this would be
$scope['participant.CheckInTime'] = Date.now();
This isn't the same as
$scope.participant.CheckInTime;
The whole string represents one object key and would have to be parsed into parts to get 2 levels out of it. Essentially it's invalid syntax for what you had hoped to accomplish
Even if it was valid there is no such object on your scope since participant is an alias for an object in the view. That object is within the array activity.Participants.
In conclusion, pass the actual object into your function and work with the whole object
If you want a generic method for multiple properties it would need to be more like:
$scope.setToNowOrNull = function (object, key){
switch(key){
case 'CheckInTime':
// code for this key
break;
}
}
Then in markup would use:
<input ng-change="setToNowOrNull(participant, 'CheckInTime')">
I suspect that you likely don't need such a generic method and can simply pass a single argument, the participant object, for that specific change handler
Within the ng-repeat, the object has its own scope, therefore when you try to write into $scope[thingtoset], instead of overriding the parent scope's corresponding object, you just create another object with the same name in the lower scope. Instead you can create an object in the upper scope, say $scope.thingHolder, and when this function is called, it can update $scope.thingHolder[thingtoset]. Then you will be able to observe the changes correctly in the upper scope too.

Number filter on input

I am having trouble getting a filter to work on a number/text input.
<input type="number" class="text-center" ng-model="redeem.redemption.Amount | number: 2">
This throws an error: Expression 'redeem.redemption.Amount | number' is non-assignable
If I remove the filter, it works. I tried applying the same filter to the angular input demos and it works fine (https://docs.angularjs.org/api/ng/filter/number). Only difference I can see is I am binding to a an object on the scope and not a value directly. Is there something easy I am missing here?
I guess that what you are trying to do is to display the "formated value" of what they enter?
Then just remove the filter from the ng-model and in your controller watch the redeem.redemption.Amount and format it when the watch gets triggered. you will also need to set a timeout in order to allow the user to type, otherwise every time that the user hits a number the watch will try to format the number and the user won't be able to type anything.
The code that you have posted will never work because ng-model establishes a 2 way data binding with the property of the scope that you indicate, that's why you can not set filters there, it will only accept a property of the scope, that will be updated and from where it will read the value when it changes. The filter is a function with one input and retrieves a different output, think about it, if you set the filter, then Angularjs won't know where it has to set the changes of of the input.
Something like this:
app.controller('MyCtrl', function($scope,$filter,$timeout) {
$scope.testValue = "0.00";
var myTimeout;
$scope.$watch('testValue', function (newVal, oldVal) {
if (myTimeout) $timeout.cancel(myTimeout);
myTimeout = $timeout(function() {
if($filter('number')(oldVal, 2)!=newVal)
$scope.testValue = $filter('number')($scope.testValue, 2);
}, 500);
});
});
http://plnkr.co/edit/WHhWKdynw0nA4rYoy6ma?p=preview
Try tweaking the delay for the timeout, right now its been set to 500ms.
you cant put filter in ng-model directive.you can do it controller using this:
redeem.redemption.Amount=redeem.redemption.Amount.toFixed(2);
or you can use jquery to prevent keypress two digits after a decimal number like this:
$('.decimal').keypress(function (e) {
var character = String.fromCharCode(e.keyCode)
var newValue = this.value + character;
if (isNaN(newValue) || parseFloat(newValue) * 100 % 1 > 0) {
e.preventDefault();
return false;
}
});
<input type="number" id="decimal" class="text-center" ng-model="redeem.redemption.Amount | number:">

Angular JS | what to pass in ng-click ternary operator to do nothing

I am trying to enable ng-click based on a condition using ternary operator (?:)
ng-click="hasPermission?Update():...."
In last parameter of ternary operator what can I pass so that nothing would happen.
Also, I don't want to create any dummy function in my JS or to write any irrelevant condition as 1=1
angular.noop() was provided to address your scenario:
<div ng-click="hasPermission ? Update() : angular.noop()">
noop() is a function that peforms no operations.
Documention Here
You can do it like this instead:
ng-click="hasPermission && Update()"
Why not:
ng-click="Update()"
$scope.Update = function(){
if($scope.hasPermission){
// do something
}
}
It will be easier to:
1.Debug.
2.Read your code.
3.Add conditions to your code in the feature.
4.Clean your htmls.
etc...
Why don't you write just
ng-click="hasPermission && Update()"
It will check weather hasPermission is not false/undefined/null it will call the update()
DEMO
Just change the value of $scope.has in above demo & see.
Terrnary operator in ng-click you should write like this
<div ng-click="hasPermission ? Update() : DontUpdate()">

Why JavaScript IF only works once?

I have JavaScript code which copies the value of input file and paste it in the text box in real time.
<script>
function copyit(){
var thephoto=document.getElementById('thephoto').value;
var fileonchange=document.getElementById('fileonchange').value;
if(!thephoto==fileonchange){
document.getElementById('fileonchange').value=thephoto;
}
}
window.setInterval("copyit()", 500);
</script>
Choose File : <input type="file" id="thephoto"><br>
Here Is the file name : <input type="text" id="fileonchange">
Sadly this only works once and then stops pasting the value when changing the file again. (I mean you should reload the page to make it work again)
Does IF have a cache or something? You can try the code by yourself to see.
The syntax is wrong. You need the != operator to denote inequality:
if (thephoto != fileonchange) {
The !thephoto actually inverses its boolean representation (i.e. true becomes false and vice versa, also null becomes true). The == actually compares the equality of the both operands.
Try changing the IF line to:
if(thephoto!=fileonchange){
BalusC is completely right, but IMHO using a timer every 500ms to do this simple task seems pretty heavy.
Why don't you simply use the onchange event of the <input type="file" />?, e.g.:
window.onload = function () {
var thephoto = document.getElementById('thephoto');
var fileonchange = document.getElementById('fileonchange');
thephoto.onchange = function () {
// this function will be executed when the user changes the file
fileonchange.value = this.value;
};
};
Check the above example here.
The input element, as the W3C says, accepts the onchange method. Why don't you do:
<input type="file" id="thephoto" onchange="copyit()">
Instead of using the dreaded setInterval?
Use !== for strict inequality.
Or, if you want to use something similar to the syntax you've written, do this:
if(!(thephoto==fileonchange)){

Categories

Resources