Update a span in a ng-repeat using ng-keyup - angularjs

In a repeater and I display some records with some data, input field and a span tag in each row. When the user enters numeric value into the input field,
I want to do a calculation on it and display the result in the span tag. This will happen on keypress using ng-keyup
I’ve tried this but its not working, probably becuse I'm not using the model correctly...
<div ng-repeat="bet in $ctrl.bets">
<input class="form-control input-sm" ng-model="$index" type="text" ng-keyup="$ctrl.getReturn($index)">
<span>Return: </span><span id="$index" ng-model="$index"></span>
</div>
And in my controller I have this
vm.getReturn = function(index){
document.querySelector('#' + index ).html(value / 2);
}
I know its way off, but can someone tell me how to do this? Ta.

1st thing you can use ng-model only with input, select & special bootstrap components, Not span element. You could use ng-bind do bind value one way.
Other thing is don't play with $index which is added & managed by ng-repeat directive itself. I'd say rather add new property inside bet(each element of bets).
Markup
<div ng-repeat="bet in $ctrl.bets">
<input class="form-control input-sm" ng-model="bet.myValue" type="text" ng-keyup="$ctrl.getReturn(bet.myValue)">
<span>Return: </span><span id="$index" ng-bind="vm.getReturn(bet.myValue)"></span>
</div>
Accordingly manage calculation in getReturn function.
vm.getReturn = function(val) {
return (val > 0 ? (val / 2): 0);
}

Related

How use multiply ng-models in AngularJS

I have textarea with ng-model 'wordset' and ng-change="onChange()"
<div>
<textarea ng-model="wordset" ng-change="onChange()"
class="form-control app-word-set"
placeholder="Enter Word Set" rows="4">
</textarea>
</div>
I have button which added new textarea in this div. I needed that already added textarea includes the same on change method that my first textarea i have. But it should use ng-model...
I want to use on method in my angularJS controller that gets values from every textarea by foreach like this:
$scope.wordSetTextarea = angular.element(document.getElementsByClassName('app-word-set'));
$scope.onChange = function() {
angular.forEach($scope.wordSetTextarea, function(value, key) {
console.log(value);
});
}
Is this possible?
With the AngularJS framework, multiple elements are added with the ng-repeat directive:
<div ng-repeat="item in itemArr">
<textarea ng-model="item.wordset"
ng-change="onChange(item,$index)"
name="'item' + $index"
class="form-control app-word-set"
placeholder="Enter Word Set" rows="4">
</textarea>
</div>
<button ng-click="addNewTextarea()">Add input</button>
$scope.itemArr = [{}];
$scope.addNewTextarea = function() {
$scope.itemArr.push({});
};
New AngularJS developers often do not realize that ng-repeat, ng-switch, ng-view, ng-include and ng-if all create new child scopes, so [data hiding problems] often shows up when these directives are involved ... [they] can be easily avoided by following the "best practice" of always have a '.' in your ng-models.
For more information, see
AngularJS ng-repeat Directive API Reference -
What are the nuances of scope prototypal / prototypical inheritance in AngularJS?

Can ng-model replace Ids?

Is there a way to avoid IDs while creating elements i.e. using ng-model it is easier to validate form fields and other stuff?
<div ng-repeat="x in TestData">
<input type="text" id="nameField-{{$index}}"/>
</div>
The above code will display the number of input boxes equal to the length of the TestData array where every text box will have a unique id "nameField-0", "nameField-1" and so on, using these IDs we can take the textbox values, validate the fields etc.
<div ng-repeat="x in TestData">
<input type="text" ng-model=""/> <!-- what shall be done here to have unique IDs -->
</div>
Although going with IDs is working fine for me but as far as I can understand If I use IDs then that will not be a pure angular way (or IDs cannot be replaced by mg-models), correct me If I am wrong.
You don't need to grab element with id/name/etc. You can use ng-model to bind your values and ng-pattern to validate them.
<div ng-repeat="x in testData">
<ng-form name="tForm">
<input type="text" name="tInput" ng-model="x.name" ng-pattern="/^[A-Z]*$/" />
<span ng-if="tForm.tInput.$error.pattern" style="color:red">Invalid!</span>
</ng-form>
</div>
See this jsbin.
In your controller add this,
$scope.nameField = [];
in ng-reapeat add this,
<div ng-repeat="x in TestData">
<input type="text" ng-model="nameField[$index]"/>
</div>
nameField will be an array with all your values.
<div ng-repeat="x in TestData" ng-init='this["nameField-"+x]'>
<input ng-model='this["nameField-"+x]'/>
</div>
You use ng-init to add new variables to the controller, "this" refer to your scope, and since the scope is an object, since this[bla] == this.bla tou are actually saying, add to my scope a variable name "nameField=" and you add the x value.
after you have created your variable, just use it in the same way in your ng-model.
If you want to show your variable's value in any div/span, just use it via ng-bind:
<div ng-bind='this["nameField-"+x]'></div>

Angularjs Input text appending number instead of adding it

When user type in number then click on "+", it will append the count instead of perform addition for the counter.
But it is working fine when performing "-" or "+" action without key in number in the input box.
<div ng-app="myApp" ng-controller ="myCtrl">
<span ng-click="count = count + 1">+</span>
<input type="text" ng-model="count" valid-number>
<span ng-click="count = count - 1" ng-show="count > 0">-</span>
</div>
fiddle : http://jsfiddle.net/shenglim/Lyugypqk/4/
Anybody can help out on this? Thanks !
simple example will work if uses ng-click="test()" and perform basic addition, if you need to retrieve from existing json which return string, Try to use parseInt() on the JSON object.
Try <input type="number">.
The data type for type="text" makes it a string and "1" + 1 = "11"
JSFiddle ~ http://jsfiddle.net/Lyugypqk/2/
Alternatively you can add two methods to increase and decrease the values into the controller and use them,
$scope.increment = function(){
$scope.count++;
};
$scope.decrement = function(){
$scope.count--;
};
<span ng-click="increment()">+</span>
<input type="text" ng-model="count" valid-number>
<span ng-click="decrement()" ng-show="count > 0">-</span>

Replace checkbox with images angularjs

I have to style/replace all checkboxes and radio buttons with images.
I can do this easily by simply adding a span tag after every input(checkbox / radio) like.
<label for="rememberme">
<input type="checkbox" class="unique" id="rememberme"/>
<span class="icon-checkbox"></span>
</label>
How can i do this in angular js.
I cannot modify all htmls with adding a span element, as if something went wrong it will take time to revert.
But i have a unique class or i can add an attribute to write a directive.
I tried using an attribute but i am unable to inspect span element generated, it is working good if i use it as an element.
If i use as an attribute it is giving an output as
<input type="text" class="form-control" custom-input="">
<input type="text" class="form-control">
<span class="icon-checkbox">Checkbox icon</span>
</input>
is this Valid ?
Plunker here
I wouldn't worry about a custom directive just to replace the checkboxes with images. You could do this with CSS like this:
<!--HTML-->
<input type="text" class="form-control checkboxwithicon">
/*CSS*/
.checkboxwithicon{
position:relative;
}
.checkboxwithicon::after{
content:url('http://icons.iconarchive.com/icons/icojam/blueberry-basic/32/check-icon.png');
position:absolute;
top:-10px;
left:15px;
}
And position the image properly so that the checkbox is hidden.
You can write a directive that does generate the span icon-checkbox after the element (it's supposed to be a checkbox) for you and make it act like an attribute, then you can tag it in every input checkbox that you want. Even something wrong happens and you are not happy with the change, you don't have to waste your time and effort to revert the things back, just modify on the directive only.
I made it working from your suggestions with out any change to HTML for easy fallback
.directive('input',function(){
return{
require: '?ngModel',
restrict:'EAC',
link:function(scope,element,attr){
var html = angular.element("<span class='icon-checkbox'>Checkbox icon</span");
if( (angular.lowercase(element[0].tagName)==="input") && (angular.lowercase(attr.type)=== "checkbox"))
element.after(html)
}
}
})
Working Plunker

How do I add a class to a div if the item in ng-repeat is not valid?

I am trying to use $invalid to add a class to a div when the input within the div is not filled out. However I just cannot work out the syntax.
<div ng-app ng-controller="miniC">
<form name="persondetails" novalidate>
<div ng-repeat="account in myAccounts" ng-class="{'has-error': account.amount.$invalid}" >
<input name="{{account.name}}" ng-model="account.amount" required="required"/>
</div>
</form>
</div>
function Account(nameArg, amountArg){
this.name = nameArg;
this.amount = amountArg;
}
The surrounding div needs to have class="has-error" when the inner item is not filled in. I have done similar on single bound elements just cant seem to get this working....
$invalid flag is not attached to the ngModel, but to the form controller (ngFormController).
In your example you're not demonstrating that you're even using ngForm, and you should, if you want angular to validate your form.
Next, you're trying to dynamically set the input's name attribute. ngForm won't like it because ngFormControll will be initialized before your expression is evaluated.
Workaround is to wrap each ng-repeat iteration inside new ngForm (ngForm can be nested and it will just work) and name your inputs with some static string value (e.g. name="amount").
So, you'll want your view written as:
<div
ng-repeat="account in myAccounts"
ng-class="{'has-error': form.amount.$invalid}"
ng-form="form"
>
<input name="amount" ng-model="account.amount" required="required"/>
</div>

Resources