Angularjs: How to get value of input without ng-model - angularjs

I need to make some inputs by ng-repeat, and in my json file I have in object where is a property called name, like this:
"url":"find_company",
"values":[
{
"name":"company name",
"type":"input_search"
},{
"name":"company_phone",
"type":"input_search"
}
]
I want to make search in DB, in search you can find by any field or by two or more field. Field called the same as property of object. So by ng-keyup I need to send to my function
search(field, value)
two arguments. I want to do something like this
<div ng-repeat="value in param.values">
<input ng-if="value.type == 'input_search'"
ng-keyup="search(value.name, this.text)"
type="text">
How can a send to function text of this input without using ng-model? Where this.text is value of input.

since you are using ng-keyup, you can retrieve input value with $event.target.value.
comment: this is fit for normal event like onclick, but not fit for angular.
refer the below example.
angular.module("app", [])
.controller("myCtrl", function($scope) {
$scope.showValue = function(val) {
alert(val);
}
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.min.js"></script>
<div ng-app="app" ng-controller="myCtrl">
<input type="test" ng-keyup="showValue($event.target.value)">
</div>

This is how you do it with ngModel:
<div ng-repeat="value in param.values">
<input ng-if="value.type == 'input_search'" ng-model="value.val" ng-keyup="search(value)" type="text">
And in your controller:
$scope.search = function( item ) {
console.log( item.val ); // Here you have the value using ngModel
console.log( item.name ); // Here you have the "name" property of the element inside the loop
}
As you can see, you CAN use ngModel and by passing the object itself to the function you can access its properties from the function in the controller.
Note that there's that this.text in the view - I don't know what it is exactly so I dropped it from the example to make things clearer, but you can use it in your code of course.

I know the question said without using ng-model. But I suspect you may want this because you want to customize when data-binding occurs. If that's the case, you can use ng-model-options with ng-change:
<input type="text" ng-model="yourModel" ng-model-options="{ updateOn: 'keyup' }" ng-change="search()" />
ng-change fires when the model has been updated, which is after keyup in this case. So the value of yourModel will be up to date when search() executes.

Related

How to use more than two ng-model in one input field

Is it possible to have more than one ng-model on one input field ?
e.g:
<input ng-model="formData.glCode" ng-model="accNumber" ng-change="accNumber = editAccountNumber(accNumber)"/>
Because all inputs where I want to apply this have ng-model set already and I also need to edit model name ng-model="accNumber"
If you can't edit the input and you are trying to bind the model to the controller use the same model which already exist on the input:
<input ng-model="formData.glCode" ng-change="formData.glCode = editAccountNumber(formData.glCode)"/>
Possible duplicate:
How to bind 2 models to one input field in Angular?
No, ngModel wasn't supposed to do things like this, at this point it is better to start relocating the logic from the view. For this scenario you could make use of $watch and get the accNumber value in controller.
Working demo :
var myApp = angular.module('myApp',[]);
myApp.controller('MyCtrl',function($scope) {
$scope.$watch('formData.glCode', function(){
console.log($scope.accNumber);
});
$scope.editAccountNumber = function(glCode) {
return glCode;
}
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myApp" ng-controller="MyCtrl">
<input type="text"
ng-model="formData.glCode"
ng-change="accNumber = editAccountNumber(formData.glCode)"/>
</div>
You can use this code: ng-model-options
<input ng-model="name" ng-model-options="{updateOn: 'blur'}">
for more detail you can try this link:
http://www.w3schools.com/angular/ng_ng-model-options.asp

AngularJS - unchanged data passed by ng-model is interpreted as undefined instead of the value

I'm using Angular to generate some inputs and populate them with data using ng-repeat. I also want to bind the data inside the input to a save changes button which takes parameters provided by ng-model directives. save changes button prints the passed arguments using the built-in JS arguments object. For some reason, unless I change the text inside the input box, the output is [undefined, undefined]. Once I change the text inside the input boxes, the correct output is printed. Why is that?
JSfiddle code.
HTML:
<div ng-app="myApp" ng-controller="MainCtrl">
<p ng-repeat = "man in men">
<label>name</label><input type="text" ng-model="mname" ng-value="man.name"><br>
<label>status</label><input type="text" ng-model="mstatus" ng-value="man.status"><br>
<button ng-click="save(mname,mstatus)">
save changes
</button>
</p>
</div>
JS:
var app = angular.module('myApp', []);
app.controller('MainCtrl', function($scope) {
$scope.men = [{
name: "jon snow",
status: "depands"
}, {
name: "rob stark",
status: "dead"
}];
$scope.save = function() {
console.log(arguments);
}
});
This is not recommended but for your specific requirement you can use ng-init to bind ng-value to your model
<p ng-repeat = "man in men">
<label>name</label><input type="text" ng-model="mname" ng-value="man.name" ng-init="mname = man.name"><br>
<label>status</label><input type="text" ng-model="mstatus" ng-value="man.status" ng-init="mstatus = man.status"><br>
<button ng-click="save(mname,mstatus)">
save changes
</button>
</p>
This wouldn't bind your changes to the original model.
Fiddle
ngModel doesn't update untill you use a key to change it, or set it from your controller. Because you are setting the field of the input using ngValue, it doesn't register to your ngModel untill you change it.
This problem is similar to how most datepickers don't work with ngModel, as they set the field with DOM-manipulation and NOT by inserting the value by "key".
You can easily fix this by using the following HTML instead:
<label>name</label><input type="text" ng-model="man.name"><br>
<label>status</label><input type="text" ng-model="man.status"><br>
I simply removed the ngValue and linked the ngModel to your "man".

ng-change not working on a text input

I am new to angular js. In my code there is color picker initialized from a text field. User changes the value of color and I want that color to be reflected as a background of a text in a span. It is not working. What is missing?
HTML:
<body ng-app="">
<input type="button" value="set color" ng-click="myStyle={color:'red'}">
<input type="button" value="clear" ng-click="myStyle={}">
<input type="text" name="abc" class="color" ng-change="myStyle={color:'green'}">
<br/>
<span ng-style="myStyle">Sample Text</span>
<pre>myStyle={{myStyle}}</pre>
</body>
Plunker - http://plnkr.co/edit/APrl9Y98Em0d6rxuzRDE?p=preview
However when I change it to ng-click it works.
ng-change requires ng-model,
<input type="text" name="abc" class="color" ng-model="someName" ng-change="myStyle={color:'green'}">
I've got the same issue, my model is binding from another form, I've added ng-change and ng-model and it still doesn't work:
<input type="hidden" id="pdf-url" class="form-control" ng-model="pdfUrl"/>
<ng-dropzone
dropzone="dropzone"
dropzone-config="dropzoneButtonCfg"
model="pdfUrl">
</ng-dropzone>
An input #pdf-url gets data from dropzone (two ways binding), however, ng-change doesn't work in this case. $scope.$watch is a solution for me:
$scope.$watch('pdfUrl', function updatePdfUrl(newPdfUrl, oldPdfUrl) {
if (newPdfUrl !== oldPdfUrl) {
// It's updated - Do something you want here.
}
});
Hope this help.
When you want to edit something in Angular you need to insert an ngModel in your html
try this in your sample:
<input type="text" name="abc" class="color" ng-model="myStyle.color">
You don't need to watch the change at all!
Maybe you can try something like this:
Using a directive
directive('watchChange', function() {
return {
scope: {
onchange: '&watchChange'
},
link: function(scope, element, attrs) {
element.on('input', function() {
scope.onchange();
});
}
};
});
http://jsfiddle.net/H2EAB/
One can also bind a function with ng-change event listener, if they need to run a bit more complex logic.
<div ng-app="myApp" ng-controller="myCtrl">
<input type='text' ng-model='name' ng-change='change()'>
<br/> <span>changed {{counter}} times </span>
</div>
...
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope) {
$scope.name = 'Australia';
$scope.counter = 0;
$scope.change = function() {
$scope.counter++;
};
});
https://jsfiddle.net/as0nyre3/1/
First at all i'm seing your code and you haven't any controller. So i suggest that you use a controller.
I think you have to use a controller because your variable {{myStyle}} isn't compile because the 2 curly brace are visible and they shouldn't.
Second you have to use ng-model for your input, this directive will bind the value of the input to your variable.

Angular.js - ng-change not firing when ng-pattern is $invalid

I am using ng-pattern to validate some form fields, and I am using ng-change with it to watch and process any changes, however ng-change (or $scope.$watch) will only fire when the form element is in the $valid state! I'm new to angular, so I don't know how to solve this issue, although I suspect a new directive is the way to go.
How can I get ng-change to fire in both $invalid and $valid form element states, with ng-pattern still setting the form element states as before?
Html:
<div ng-app="test">
<div ng-controller="controller">
<form name="form">
<input type="text" name="textbox" ng-pattern="/^[0-9]+$/" ng-change="change()" ng-model="inputtext"> Changes: {{ changes }}
</form>
<br>
Type in any amount of numbers, and changes should increment.
<br><br>
Now enter anything that isn't a number, and changes will stop incrementing. When the form is in the $invalid state, ng-change doesn't fire.
<br><br>
Now remove all characters that aren't numbers. It will increment like normal again. When the form is in the $valid state, ng-change will fire.
<br><br>
I would like ng-change to fire even when the the form is $invalid.
<br><br>
form.$valid: <font color="red">{{ form.$valid }}</font>
</div>
</div>
Javascript:
angular.module('test', []).controller('controller', function ($scope) {
$scope.changes = 0;
$scope.change = function () {
$scope.changes += 1;
};
});
I have created a working JS Fiddle which shows the problem I am having.
http://jsfiddle.net/JAN3x/1/
By the way, this angular issue also seems to be relevant:
https://github.com/angular/angular.js/issues/1296
You can change the behavior of your input by using ng-model-options.
Just add this attribute to your input and the ng-change event will fire:
ng-model-options="{allowInvalid: true}"
see: https://docs.angularjs.org/api/ng/directive/ngModelOptions
you just need to add
ng-model-options="{ updateOn: 'default' , allowInvalid:'true'}"
this indicates that the model can be set with values that did not validate correctly instead of the default behaviour.
Edit This was answered when ng-model-options was not available. Please see the top-voted answer.
you can write a simple directive to listen input event.
HTML:
<input type="text" name="textbox" ng-pattern="/^[0-9]+$/" watch-change="change()" ng-model="inputtext"> Changes: {{ changes }}
JS:
app.directive('watchChange', function() {
return {
scope: {
onchange: '&watchChange'
},
link: function(scope, element, attrs) {
element.on('input', function() {
scope.$apply(function () {
scope.onchange();
});
});
}
};
});
http://jsfiddle.net/H2EAB/
Inspired by the Li Yin Kong ingenious solution :
His solution has an issue concerning the ndModel update (see the comments of his post).
My fix essentially changes the scope type of the directive. It lets directive access to controller scope (and methods)
Then, watch-change directive does not need an "instruction to eval" (change()) anymore, but only the "name of the controller method to call" (change).
And to get the new value of the input in this function, I pass the context (this = the input itself). So I can get the value or any property of it.
This way, we don't care about ngModel updates (or if the form is invalid, which was another issue of the initial solution : ngModel is deleted if form is invalid)
HTML :
<input type="text" name="textbox" ng-pattern="/^[0-9]+$/" watch-change="change" ng-model="inputtext">
JAVASCRIPT :
app.directive('watchChange', function() {
return {
restrict : 'A',
link: function(scope, element, attrs) {
element.on('input', function(){
scope[attrs.watchChange](this);
})
}
};
});
DEMO : http://jsfiddle.net/msieurtoph/0Ld5p2t4/

How can I add a class to an input if the input is changed with AngularJS?

I coded the following in my form:
<td><input type="text" ng-model="row.title" /></td>
When I look at my DOM with Chrome developer tools I see the following:
<input type="text" ng-model="row.title" class="ng-pristine ng-valid">
How can I make it so that when there is a change made to the input that the input has a class added to it?
There are two good ways to approach this problem:
1. Use the built-in ng-dirty class that Angular puts on the element.
When you change an input managed by Angular, it adds some CSS classes to the input for various states. These include:
ng-pristine - the input has not been modified
ng-dirty - the input has been modified
So, if you can modify your CSS to be based off the .ng-dirty class, you're good to go.
2. Use a form directive with the $dirty flag.
When you use a form element, Angular assigns a FormController instance on the scope with the same name as the name attribute on the form; each input inside the form gets attached to that FormController instance as a property, again with the same name as the name attribute on the input. For example,
<form name="myForm">
<input type="text" name="myInput">
</form>
gives you
$scope.myForm.myInput
Each input property has some of its own properties on it, including $pristine and $dirty; these work just like the CSS classes listed above. Thus, you can check for the $dirty flag on the input and use ng-class to conditionally apply a class to the element. An example:
<div ng-controller="MainController">
<form name="myForm">
<input name="myInput" ng-model="model" ng-maxlength="3"
ng-class="{changed: myForm.myInput.$dirty}">
</form>
</div>
You can find a working example here: http://jsfiddle.net/BinaryMuse/BDB5b/
Take a look at this jsfiddle: http://jsfiddle.net/hNrEV/2/
The main idea is using $scope.$watch to watch for changes to the input box. I gave it an id of rowTitle, and used a directive called watchRowTitle that watches for changes to $scope.row.title, and adds a class 'red' that colors the text red whenever the text in the input box is equal to 'wrong title'.
It is probably good practice to do DOM manipulation in directives. Here, the watchRowTitle directive returns an object with 4 keys:
template - the html that replaces the watch-row-title tag. we dont need this here
scope - Here we make use of an isolated scope. Basically, the '=' establishes a 2-way data binding between between scope.title inside the watch-row-title directive and the $scope.row.title value inside the MyCtrl controller.
restrict - We give it a value of E, which stands for element. So this restricts the use of the watch-row-title directive within html tags, in other words: <watch-row-title></watch-row-title>
link - this is the link function, where the interesting stuff happens. In here, we use scope.$watch on title. We have to supply a function with 2 parameters newValue and oldValue (you can name them to something else, but naming them this way is more meaningful), that holds the new and old values of the variable being watched. Whenever the scope.title variable becomes the string 'wrong title', it adds the CSS class 'red' to the input box with id rowTitle (notice how the text in the input box turns red). Otherwise, it removes that CSS class. This portion is done using JQuery.
HTML:
<div ng-app="myApp" ng-controller="MyCtrl">
<input id="rowTitle" type="text" ng-model="row.title" class="ng-pristine ng-valid" />
<watch-row-title title="row.title"></watch-row-title>
</div>
CSS:
.red {
color: red;
}
JavaScript:
angular.module('myApp', [])
.controller('MyCtrl', [
'$scope',
function ($scope) {
$scope.row = {};
}
])
.directive('watchRowTitle', [
function () {
return {
template: '',
scope: {
title: '='
},
restrict: 'E',
link: function(scope, element, attr) {
scope.$watch('title', function(newValue, oldValue) {
if (newValue === 'wrong title') {
$('#rowTitle').addClass('red');
} else {
$('#rowTitle').removeClass('red');
}
});
}
};
}
]);
HTML
<input type="text" id="inputTitle" ng-model="row.title" />
JS
$scope.$watch('row.title', function(newValue) {
// Add CSS class on input
$('#inputTitle').addClass('YourCSSClass');
}, true);

Resources