How to propogate a changing scope variable through a function in AngularJs? - javascript

For example, if I have the following case:
function ACtrl($scope) {
$scope.title = "Title";
$scope.funkyString= funkyAndComplexStuff($scope.title);
function funkyAndComplexStuff(title) {
/*...*/
return title;
}
}
With html:
<div ng-app>
<div ng-controller="ACtrl">
<div>
{{title}} and length {{funkyString}}
<input type="text" ng-model='title' />
</div>
</div>
</div>
I would like the $scope.funkyString to update every time $scope.title gets changed.
As far as I see I have 2 options:
Using a watch on the variable
Creating a filter I could apply on $scope.funkyString
But both of those sound unndecessarily heavy. Is there anything else I could use to post-process the data as soon as it gets changed?
EDIT:
Modified my example so that people are hopefully less confused.

I would try something like this, so it can handle changes to $scope.title from other fields of code also
<div ng-controller="ACtrl">
<div>
{{title}} and length {{ funkyAndComplexStuff(title) }}
<input type="text" ng-model='title' />
</div>
</div>

You could do title.length as #ssilas777 has suggested. You can also set the $scope variable to be a function. As I understand it, the function will be called during the scope's $digest cycle, which will fire when any bound model changes. See this plunkr: http://plnkr.co/edit/9xspXj5ND8seEX2LNeMe?p=preview
See this HTML:
<input type="text" ng-model="title" />
Num chars: <span ng-bind="numCharsInTitle()"></span>
and the JS:
$scope.title = "The Title";
$scope.numCharsInTitle = function() {
return $scope.title.length;
}

Like ssilas777 and Charlie S and you said you can use $watch, custom $filter or function in $scope
But for me it's complicated to maintain code with function linked to the view. I prefere using $watch because all the processing is in the controller and only $scope.numberOfChars is present in the view.
If you use this many time, I would suggest you to create a custom filter.
angular.module('app',[])
.controller('ACtrl',
function ($scope) {
$scope.title = "Title";
getNumberChars($scope.title);
function getNumberChars(title) {
$scope.numberOfChars = title.length;
};
$scope.getNumberChars = function() {
return $scope.title.length;
};
$scope.$watch('title',getNumberChars);
})
.filter('customFilter', function() {
return function(input) {
return input.length;
};
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app">
<div ng-controller="ACtrl">
<div>
{{title}} and length {{numberOfChars}} or {{title.length}} or {{getNumberChars()}} or {{title | customFilter}}
<input type="text" ng-model='title' />
</div>
</div>
</div>

ng-change could be a simple solution depending on the element to which your title model is bound. If it's an input like in the example this might could work:
app.controller('MainCtrl', function($scope) {
$scope.title = "Title";
$scope.funkyAndComplexStuff = function(title) {
/*...*/
$scope.funkyString = title.length;
}
});
...
<body ng-controller="MainCtrl">
{{title}} and length {{funkyString}}
<input type="text" ng-model='title' ng-change="funkyAndComplexStuff(title)" />
</body>

Why not just:
function ACtrl($scope) {
$scope.title = "Title";
$scope.funkyAndComplexStuff = function () {
/*..do stuff with $scope.title..*/
return $scope.title; // or whatever
}
}
With html:
<div ng-app>
<div ng-controller="ACtrl">
<div>
{{title}} and length {{funkyAndComplexStuff()}}
<input type="text" ng-model='title' />
</div>
</div>
</div>
Not sure why somebody downvoted, but here is a demo: http://jsfiddle.net/xhdk3f25/1/

Related

How access form in ng-repeat?

Here is clear exampel about forms:
<div ng-form="namesForm_{{$index}}" ng-repeat="name in names">
<input type="text"
name="input_{{$index}}_0"></input>
<!-- ... -->
Ok, but how I should access $valid field from form? E.g this does not work:
{{namesForm_$index.$valid}}
Even {{namesForm_$index}} outputs 0.
It is need to "inline" $index before {{}} resolve a variable name. How to do that?
It's not easy to get it inside of single {{ }} expression, but if you only want to use it in directives accepting expressions without handlebar (like ng-disabled), you can achieve that:
<div ng-app>
<ng-form name="namesForm_{{$index}}" ng-repeat="name in [1, 2]">
<input type="text"
placeholder="{{$index}}"
ng-required="true"
ng-model="test"
name="hey" />
<button ng-disabled="!namesForm_{{$index}}.$valid">
send
</button>
<br />
</ng-form>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.1/angular.min.js"></script>
{{ IsFormValid($index) }}
$scope.IsFormValid = function(index) {
var form = angular.element("formName" + index);
return form.$valid;
};
UPDATED
Working example:
{{ IsFormValid($index) }}
$scope.IsFormValid = function(index) {
var form = angular.element(document.getElementById('#bucketForm-' + index);
return form.$valid;
};
New Approach
The below is an example for dynamic ngModel, same can be replicated for form name :
$scope.formData = {};
$scope.formData = {
settings:
{
apiEndpoint: '',
method: 'get'
},
parameters: {}
};
<div class="form-group" ng-repeat="parameter in apiParameters">
<label for="{{parameter.paramName}}" class="col-sm-2 control-label">{{parameter.paramTitle}}</label>
<div class="col-sm-3">
<input type="text" class="form-control" name="{{parameter.paramName}}" id="{{parameter.paramName}}" ng-model="formData.parameters[parameter.paramName]" placeholder="{{parameter.paramTitle}}">
</div>
</div>

How to display ng model value to another page

I have an html page with angular in which ng model returns a address and I want to display the same address in other html page. How to do it? And my code is
<input type="text" class="form-control" ng-model="Item" placeholder="Enter the IP Address"/>
You can do similarly like this:
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope,$rootScope) {
$rootScope.$on('eventName', function(event, args) {
$scope.emitMessage = args;
});
})
.controller('myCtrl2', function($scope,$rootScope) {
$scope.onclick = function() {
$rootScope.$emit('eventName',{msg: 'my message'});
};
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.min.js"></script>
<div ng-app="myApp">
<div ng-controller="myCtrl">
<p>Message Emitted: {{emitMessage.msg}}</p>
</div>
<div ng-controller="myCtrl2"
<button ng-click="onclick()"> click me to emit message</button>
</div>
</div>

Angular JS collect all input values from a div

I am new to Angular JS, I created a div with input elements and I didn't use ng-model for input boxes.
<div class="row">
<br>
<div class="col-sm-10" id="rankingForm" >
<p ng-repeat=" x in $ctrl.outputProductAttributeValueList">
{{x}} <input type="text" />
</p>
<br>
<button type="submit" ng-click="$ctrl.onRankingFormSubmit()"> SUBMIT</button>
</div>
</div>
When I click on submit button I have to access all input values .Please help me how to do that .. I tried as below.
angular.module("productList")
.component("productList",{
templateUrl : "product-list/product-list.template.html",
controller : ["$http" ,"$scope","$document",function productListController($http,$scope,$document){
var self = this;
self.outputProductAttributeValueList =[ "age", "gender","all"];
self.onRankingFormSubmit = function () {
var queryResult = $document[0].getElementById("rankingForm")
console.log(queryResult);
// HERE queryResult is printing how to proceed further
};
}]
});
Now I want to collect all those input values dynamically created by ng-repeat. Please tell me how to do that ?
AngularJS ngModel is the standard approach for binding the view into the model instead of interacting directly with the DOM.
You can get all the inputs within the div id="rankingForm" you can do:
var inputs = $document[0]
.getElementById('rankingForm')
.getElementsByTagName('input');
Or by using Document.querySelectorAll():
var inputs = $document[0].querySelectorAll('#rankingForm input');
Once you have the inputs than iterate over all of them to get the values.. Notice that I have added attribute name to the inputs:
Code whitout ngModel:
angular
.module('App', [])
.controller('AppController', ['$scope', '$document', function ($scope, $document) {
$scope.outputProductAttributeValueList = ['age', 'gender', 'all'];
$scope.onRankingFormSubmit = function () {
var inputs = $document[0].querySelectorAll('#rankingForm input');
inputs.forEach(function(input) {
console.log(input.name + ': ' + input.value);
});
};
}]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.9/angular.min.js"></script>
<div ng-app="App" ng-controller="AppController" class="row">
<br>
<div class="col-sm-10" id="rankingForm" >
<p ng-repeat="x in outputProductAttributeValueList">
{{x}} <input type="text" name="{{x}}" />
</p>
<br>
<button type="submit" ng-click="onRankingFormSubmit()">SUBMIT</button>
</div>
</div>
Code with ngModel:
angular
.module('App', [])
.controller('AppController', ['$scope', '$document', function ($scope, $document) {
$scope.outputProductAttributeValueList = ['age', 'gender', 'all'];
// Model inputs
$scope.inputs = {};
$scope.onRankingFormSubmit = function () {
$scope.outputProductAttributeValueList.forEach(function(input) {
// Access to model inputs: $scope.inputs[input]
console.log(input + ': ' + $scope.inputs[input]);
});
};
}]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.9/angular.min.js"></script>
<div ng-app="App" ng-controller="AppController" class="row">
<br>
<div class="col-sm-10" id="rankingForm" >
<p ng-repeat="x in outputProductAttributeValueList">
{{x}} <input type="text" ng-model="inputs[x]" />
</p>
<br>
<button type="submit" ng-click="onRankingFormSubmit()">SUBMIT</button>
</div>
</div>

reseting input field after entering data

i have one input box, and im working with scanner that automatic inputs numbers when scans something, now i want to automatically assign that value to some variable, and delete it so it can get another input, any ideas?
html
<ion-view hide-nav-bar="true">
<ion-content class="padding"><br>
<label class="item item-input">
<input type="number" ng-model="code" id="code" name="theInput" auto-focus>
</label>
<div class="tt"><br><br>
Code : <span class="art">{{code}}<br><br></span>
</div><br>
<button ng-click="clear(code)" class="button button-positive">
Clear
</button>
</ion-content>
</ion-view>
js
.controller('PriCtrl', function($scope) {
window.onload = function() {
document.getElementById("code").focus();
};
$scope.clear= function(code){
$scope.val = code;
document.getElementById("code").value = '';
}
just one line change
$scope.clear= function(code){
$scope.val = code;
$scope.code = ''; //ng-model of input is code
}
you should read about how angular data binding is working
If a variable is in the scope the view can access it. if you modify the variable value the in the controller side the view will be updated automatically and vice versa.
You should avoid using jQuery as much as you can and manipulating DOM from controller like this :
`document.getElementById("code").value = '';`
is strictly the same as $scope.code = '';
this is a plunker : http://plnkr.co/edit/u3loqpxYIBMX65O9FXGD?p=preview
i will create a array to store the input
js :
var app = angular.module('app', []);
app.controller('MainCtrl', function($scope) {
$scope.selected = [] ;
$scope.code = null ;
$scope.next = function(){
$scope.selected.push( $scope.code );
$scope.code = null
}
});
HTML :
<body ng-controller="MainCtrl">
<ion-view hide-nav-bar="true">
<ion-content class="padding"><br>
<label class="item item-input">
<input type="number" ng-model="code" id="code" name="theInput" auto-focus>
</label>
<div class="tt"><br><br>
Code : <span class="art">{{code}}<br><br></span>
</div><br>
<button ng-click="next()" class="button button-positive">
scan next
</button>
</ion-content>
</ion-view>
<pre>{{selected|json}}</pre>
</body>
In Angular, try to never do something like this document.getElementById("code").value = '';.
You could simply watch the code variable for changes, and if it gets a new value, you copy it over into a values list and then delete the value from code.
.controller('PriCtrl', function($scope) {
$scope.$watch('code', function(newVal, oldVal) {
if (newVal != '') {
$scope.codelist.push(newVal);
$scope.code = '';
}
});
}

ng-model in ng-repeat become undefined

Using Javascript with angularJs, I kind the following code :
JS
$scope.myObj = {
'sthg': '',
'a': [{
'b' : ''
}]
}
HTML
<p ng-repeat="radio in fiche.radios">
<input type="text" ng-model="radio.code" placeholder="Numéro de cliché" ng-required="true" />
<span >
<button type="button"ng-click="removeRadioList($index);" ng-disabled="fiche.radios.length === 1">
<i>X</i>
</button>
</span>
</p>
http://plnkr.co/edit/LOgk7Nudse0srS7Bs1G6?p=preview
In my App $scope.myObj.a[0].b is undefined with the ng-repeat (if I remove ng-repeat, it will be defined).
In the plunkr it is defined even after the run of ng-repeat, but I managed to have the behaviour when I enter something in the input and then delete it.
I don't get what's hapening, I would like to understand why and if it is a good way to do ?
Beacause you set ng-required="true" on your input tag angular wouldn't bind empty value to your model thous when you delete value from input your console shows you radios.code as undefined.
Please see below for working demo:
(function() {
"use strict";
var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope, $log) {
$scope.ficheInit = {
'user_id': '',
'radios': [{
'code': ''
}]
};
$log.log($scope.ficheInit);
$scope.fiche = angular.copy($scope.ficheInit);
$log.log($scope.fiche);
$scope.addRadioList = function() {
$scope.fiche.radios.push({
'code': ''
});
}
$scope.removeRadioList = function(i) {
$scope.fiche.radios.splice(i, 1);
}
$scope.disableAddRadio = function() {
console.log($scope.fiche.radios);
return !(angular.isDefined($scope.fiche.radios[$scope.fiche.radios.length - 1].code) || $scope.fiche.radios.length < 1);
}
});
}());
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="plunker">
<div ng-controller="MainCtrl">
<button ng-click="showForm=true;">SHOW</button>
<div ng-show="showForm">
<button ng-click="addRadioList();" ng-disabled="disableAddRadio()">Ajouter un cliché</button>
<p ng-repeat="radio in fiche.radios">
<input type="text" ng-model="radio.code" placeholder="Numéro de cliché" />
<span>
<button type="button" ng-click="removeRadioList($index);" ng-disabled="fiche.radios.length === 1">
<i>X</i>
</button>
</span>
</p>
</div>
{{fiche.radios}}
</div>
</div>

Categories