Angular/JS get two $event.target.value in one method - angularjs

I am trying to do a range from -> to search of postal codes. I have two input fields and a simple method. Is it possible to use a method with 2 arguments?
Here is my method:
searchPostalCode(from:number, to:number):void{
console.log('from:' + from);
console.log('to:' + to);
}
And my inputs:
<input type="text" class="form-control col-sm-1" placeholder="from" (input)=searchPostalCode($event.target.value)>
<input type="text" class="form-control col-sm-1" placeholder="to" (input)=searchPostalCode($event.target.value)>

I'd say the most straightforward way would be to have two properties on the component and two methods updating those:
postalCodeFrom: number;
postalCodeTo: number;
updateFrom(value: number): void {
this.postalCodeFrom = value;
this.search();
}
updateTo(value: number): void {
this.postalCodeTo = value;
this.search();
}
search(): void {
// Make better checks - this will fail on 0
if (!this.postalCodeFrom || !this.postalCodeTo) {
// run some logic?
return;
}
// run the actual search.
}
Then have your inputs bound to that method:
<input type="text" class="form-control col-sm-1" placeholder="from" (input)=updateFrom($event.target.value)>
<input type="text" class="form-control col-sm-1" placeholder="to" (input)=updateTo($event.target.value)>
Of course there are other ways (like using RxJS) but the above should be good enough for the start.

Maybe you should use form module and do something like this.
myForm: FormGroup;
from = '';
to = '';
inside ngOnInit:
this.myForm = this.formBuilder.group({
from: [this.from],
to: [this.to]
});
this.myForm.controls['from'].valueChanges.subscribe(value => {
console.log(value);
});
this.myForm.controls['to'].valueChanges.subscribe(value => {
console.log(value);
});
and HTML:
<form [formGroup]="myForm">
...
<input type="text" name="from" [(ngModel)]="from" formControlName="from" placeholder="from"/>
<input type="text" name="to" [(ngModel)]="to" formControlName="to" placeholder="to"/>
...
</form>

Related

How to use one controller for multiple inputs with the same logic?

I have the following scenario, one form with multiple inputs and i need to calculate every input the same way but return the values to different fields
<div class="row">
<input type="number" min="1" class="form-control" id="InputValorFOR" placeholder="" ng-change="findModifier()" ng-model="atrb.for">
<p>{{mod.for}}</p>
</div>
<div class="row">
<input type="number" min="1" class="form-control" id="InputValorDES" placeholder="" ng-change="findModifier()" ng-model="atrb.des">
<p>{{mod.des}}</p>
</div>
the controller:
app.controller('atributosCtrl', function($scope){
findModifier = function() {
if ($scope.atrb > 1 && $scope.atrb <10)
{
if ($scope.atrb % 2 == 0)
{
$scope.mod = (($scope.atrb / 2) - 5);
}
}
};
$scope.$watch('atrb', findModifier); });
I want to change the value of mod.for or mod.des without having to write a controller for each input. but i don't how to pass the name of the model from the input that i'm modifying
I don't know what exactly you want, but I made some changes on your code to make it working. Please tell me what you want in comments here and I'll can help you.
Your HTML modified:
<body ng-controller="atributosCtrl">
<div class="row">
<input type="number" min="1" class="form-control" id="InputValorFOR" placeholder="" ng-change="findModifier('for')" ng-model="atrb.for">
<p>{{mod.for}}</p>
</div>
<div class="row">
<input type="number" min="1" class="form-control" id="InputValorDES" placeholder="" ng-change="findModifier('des')" ng-model="atrb.des">
<p>{{mod.des}}</p>
</div>
</body>
Your JS modified:
app.controller('atributosCtrl', function($scope){
$scope.atrb = {
for: null,
des: null
};
$scope.mod = {
for: null,
des: null
};
$scope.findModifier = function(type) {
$scope.mod[type] = null;
if ($scope.atrb[type] > 1 && $scope.atrb[type] <10)
{
if ($scope.atrb[type] % 2 === 0)
{
$scope.mod[type] = (($scope.atrb[type] / 2) - 5);
}
}
}
});
Plunker:
https://plnkr.co/edit/aCNJQyfYXZ5vU1rc381S
I think you are expecting somethin like this. You can write a custom directive with a link function like below
(function () {
"use strict";
angular.module("app").directive("notifypropertychanged", notifypropertychanged);
function notifypropertychanged() {
var directive = {
require: "ngModel",
link: function ($scope, element, attrs, ngModel) {
$scope.$watch(attrs["notifypropertychanged"], function (newVal, oldVal) {
var initialValue = attrs["oldvalue"];
});
}
};
return directive;
}
})();
Apply this directive on your input
<input type="number" min="1" class="form-control" notifypropertychanged="atrb.des" oldvalue=" {{::atrb.des}} " id="InputValorDES" placeholder="" ng-model="atrb.des">
whenever the value change it will hit on custom watch
I hope this helps

Tyepahead search results misplaced with validation

I am using a validation plug-in based on jQuery validation in my AngularJS app (which is built on top of a jQuery library).
When I use ui bootstrap Typeahead with validation the search results are misplaced.
Plunkr:
http://plnkr.co/edit/ZYP58GxITghkTqE7PNHy
HTML (help.html)
<div class="form-group">
<label for="category">Category "{{formData.category}}"</label>
<input class="form-control" type="text" name="category" id="category" placeholder="Search..." ng-model="formData.category" typeahead="obj.name for obj in getCdOnCat($viewValue)" typeahead-editable="false" typeahead-loading="loadingLocations" required>
</div>
JS (script.js) - HelpController
//Typeahead: Category Search
$scope.getCdOnCat = function (searchVal) {
return dataFactory.getCdOnCategory(searchVal).then(function (response) {
return response.data.categories;
}, function (error) {
console.log('Error: dataFactory.getCdOnCategory');
});
};
$scope.$watch('formData.category', function (value) {
if (value === "No matching categories") {
$scope.formData.category = "";
}
});

UI Bootstrap Typeahead not returning async values

I am trying to do an autocomplete search using UI Bootstrap Typeahead to select a category from a database.
I have set up an example database with 4 categories, the final one will contain more than a thousand categories.
When I start typing, the search results return 4 rows (so something must be working, because I tried to change the number of rows in the DB and the search result mirrors the total number of rows) but with no value. However, it doesn't matter what I write so it doesn't seem to be matching.
HTML
<input class="form-control" type="text" name="category" id="category" placeholder="Search..." ng-model="asyncSelected" typeahead="name for name in getCdOnCat($viewValue)" typeahead-loading="loadingLocations" required>
controller.js
//Typeahead: Category Search
$scope.getCdOnCat = function (searchVal) {
return dataFactory.getCdOnCategory(searchVal, globalVal_accessToken, globalVal_storeId).then(function (response) {
console.log(response.data.categories);
return response.data.categories;
}, function (error) {
console.log('Error: dataFactory.getCdOnCategory');
});
};
service.js
app.factory("dataFactory", function ($http) {
var factory = {};
factory.getCdOnCategory = function (searchVal, accessToken, storeId) {
return $http.get('data/getCdOnCategory.aspx?searchVal=' + searchVal + '&accessToken=' + accessToken + '&storeId=' + storeId)
};
return factory;
});
JSON
{ "categories":[
{ "name": "Clothes" },
{ "name": "Cypress" },
{ "name": "Citrus" },
{ "name": "Cats" }
] }
Please see here http://plnkr.co/edit/F4n1kNOHfZ9f3Zz63x2P?p=preview
change
<input class="form-control" type="text" name="category" id="category"
placeholder="Search..." ng-model="asyncSelected"
typeahead="name for name in getCdOnCat($viewValue)" typeahead-loading="loadingLocations"
required>
to
<input class="form-control" type="text" name="category" id="category"
placeholder="Search..." ng-model="asyncSelected"
typeahead="obj.name for obj in getCdOnCat($viewValue)" typeahead-loading="loadingLocations"
required>

How to dynamically change input value

I'm trying to show some editable results to the users, so I show them through an input field. This is a basic example of what I'm doing:
<div class="form-group">
<label>First number</label>
<input type="text" ng-model="first" ng-required="true" class="form-control">
</div>
<div class="form-group">
<label>Second number</label>
<input type="text" ng-model="second" ng-required="true" class="form-control">
</div>
<div class="form-group">
<label>The sum is: {{first + second }}</label>
<input type="text" ng-model="result" ng-required="true" class="form-control">
</div>
In the result's div, I used a label to test if the result is being obtained correctly, and it is. But if I edit the first or second values, the input's result doesn't update.
This is the controller used (yeah, the form is in a modal):
var ModalInstanceCtrl = function ($scope, $modalInstance) {
$scope.result = $scope.first + $scope.second;
$scope.confirm = function () {
$modalInstance.close(result);
};
$scope.cancelNewBet = function () {
$modalInstance.dismiss('cancel');
};
};
I thought the value was supposed to get automatically updated once I define how it is obtained. But clearly it misses something to change the result through script...
Thanks in advance.
What do you want to happen when the user edits the results input? Do you want the data binding to break (I assume not and ignore this possibility)? Do you want one of the inputs to adjust to the proper value?
If you only want to display the output, do this, in your controller:
$scope.result = function() { return $scope.first + $scope.second; }
And in your view:
{{ result() }}
But if you want the user to be able to edit the result and (let's say) have second be assigned (result - first), then you'd want something like this in your view (by the way, note the type="number"):
<input type="number" ng-change="adjustResult()" ng-model="first">
<input type="number" ng-change="adjustResult()" ng-model="second">
<input type="number" ng-change="adjustInput()" ng-model="result">
And in your controller:
$scope.adjustResult = function() {
$scope.result = $scope.first + $scope.second;
};
$scope.adjustResult(); // initialize result
$scope.adjustInput = function() {
$scope.second = $scope.result - $scope.first;
}

Two-way binding with range and number input in AngularJS

I'm just starting to play around with AngularJS and trying to understand the binding technique. For starters, I tried to make a simple conversion calculator (dozens to pieces, pieces to dozens). That worked well, but when I tried to bind both a range input and a number input to the same model property the number input does not update when the range value is adjusted. I have a jsfiddle showing the behavior:
common javascript for broken and working fiddles:
var myApp = angular.module('myApp', []);
myApp.controller('CalcCtrl', function ($scope) {
var num = 0.0;
$scope.qty = new Quantity(12);
$scope.num = num;
});
function Quantity(numOfPcs) {
var qty = numOfPcs;
var dozens = numOfPcs / 12;
this.__defineGetter__("qty", function () {
return qty;
});
this.__defineSetter__("qty", function (val) {
qty = val;
dozens = val / 12;
});
this.__defineGetter__("dozens", function () {
return dozens;
});
this.__defineSetter__("dozens", function (val) {
dozens = val;
qty = val * 12;
});
}
BROKEN FIDDLE
html:
<div ng-controller="CalcCtrl">
<form>
<label for="pcs">Pieces:</label>
<input type="number" min="0" ng-model="qty.qty" size="20" id="pcs"
/>
<input type="range" min="0" max="100" ng-model="qty.qty" />
<br/>
<label for="numOfDozens">Dozens</label>
<input type="number" min="0" ng-model="qty.dozens" size="20"
id="numOfDozens" />
</form>
</div>
However, binding two number inputs to the same model property seems to work fine as shown in this fiddle:
WORKING FIDDLE
html:
<div ng-controller="CalcCtrl">
<form>
<label for="pcs">Pieces:</label>
<input type="number" min="0" ng-model="qty.qty" size="20" id="pcs"
/>
<input type="number" min="0" max="100" ng-model="qty.qty" />
<br/>
<label for="numOfDozens">Dozens</label>
<input type="number" min="0" ng-model="qty.dozens" size="20"
id="numOfDozens" />
</form>
</div>
Any ideas how to get a range and number input bound to a single model property in AngularJS? Thanks.
The problem here is that the input type="range" works with Strings and not with Numbers (while input type="number" only works with Numbers).
http://www.w3.org/wiki/HTML/Elements/input/range
The range state represents a control for setting the element's value to
a string representing a number.
If you add val = parseInt(val) as your first instruction on the qty setter it should work:
this.__defineSetter__("qty", function (val) {
val = parseInt(val);
qty = val;
dozens = val / 12;
});
jsfiddle: http://jsfiddle.net/bmleite/2Pk3M/2/
I think this solution is more generic.
myApp.directive('input', function() {
return {
restrict: 'E',
require: '?ngModel',
link: function(scope, element, attrs, ngModel) {
if ('type' in attrs && attrs.type.toLowerCase() === 'range') {
ngModel.$parsers.push(parseFloat);
}
}
};
});
full explanation
You can solve it using ng-model-options. I changed jsfiddle and here is the code:
html:
<div ng-controller="CalcCtrl">
<form>
<label for="pcs">Pieces:</label>
<input type="number" min="0" ng-model="qty.qty" size="20" id="pcs" ng-model-options="{ getterSetter: true }"/>
<input type="range" min="0" max="100" ng-model="qty.qty" ng-model-options="{ getterSetter: true }"/>
<br/>
<label for="numOfDozens">Dozens</label>
<input type="number" min="0" ng-model="qty.dozens" size="20"
id="numOfDozens" ng-model-options="{ getterSetter: true }"/>
</form>
</div>
js:
var myApp = angular.module('myApp', []);
myApp.controller('CalcCtrl', function ($scope) {
var num = 1.0;
$scope.qty = {
qty:function (val) {
return arguments.length ? (num = parseFloat(val)) : num;
},
dozens: function (val) {
return arguments.length ? (num = val*12) : num/12;
}
};
});

Resources