angular.js hidden input data not updating - angularjs

I'm having trouble with hidden input. I have this html:
<form ng-controller="FormCtrl as a" ng-submit="a.something(a.form)" novalidate>
<input type="hidden" ng-model="a.form.unitPrice" ng-init="a.form.unitPrice = product.prices[0].price" value="{{a.form.option}}">
...
Value of a.form.unitPrice is dinamically changing. Controller:
this.addToCart = function(a) {
console.log(a);
console.log ($scope.a.form.unitPrice);
};

Try calling
$scope.$digest();
I've noticed also that angular is not updating not visible elements.

Related

ng-change triggered before value is updated

I have a form which needs to save data each time something is changed. I've used ng-change on all form elements to trigger a form validation and a save. However in case of radio buttons, ng-change is triggered before the actual value is updated, thus resulting in an invalid form on the first try, and an outdated form all subsequent times.
I've set up a JSFiddle to illustrate this. The console prints out whether the form is valid or not. The same applies if I were to print the value of $scope.form.test.$modelValue.
// HTML
<div ng-controller="MyCtrl">
<form name="form">
<input type="radio" name="test" ng-model="test" value="yes" required ng-change="checkRadios()" /> Yes<br/>
<input type="radio" name="test" ng-model="test" value="no" required ng-change="checkRadios()"/> No
</form>
</div>
// JS
var myApp = angular.module('myApp',[]);
function MyCtrl($scope) {
$scope.test = null;
$scope.checkRadios = function(){
console.log($scope.form.test.$modelValue);
}
}
Is my logic faulty, is this a valid bug, or does it work as expected? In the last case, what can I do to always get the actual value?
You need a delay to get the updated value of the $scope.form, so it is possible to achieve by using $timeout
http://jsfiddle.net/loen22/w7dpx57f/
$scope.checkRadios = function(){
$timeout(function () {
console.log($scope.form.$valid);
});
}

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 - Change path, Same controller, don't reload scope

I know it's been asked so many times here and I found it too. But it could not solve my problem.
Here is the case. I have one AngularJS application.
I have a list page. I have a button to add. When I click on add button, a pop-up window will come with a form. I want to change the URL when the pop-up comes but in the same controller.
Also I would like to add some other buttons on each, some html display as popup-or other location, but same controller without reloading all scope when url changes.
What I have tried.
app.js
var WebClientApp = angular.module('WebClientApp', [
'ngCookies',
'ngResource',
'ngSanitize',
'ui.bootstrap',
'ngRoute'
]);
WebClientApp.config(function ($routeProvider) {
$routeProvider
.when('/groups/:template', {
templateUrl: 'groups.html',
controller: 'GroupCtrl'
}
groups.html
<div>
<button ng-click="showAdd()">Add Group</button>
<div ng-include src="views/listpage.html">
<div ng-if="addGroupModal" class="popup-modal">
<form name="addGroup" ng-submit="addandEditGroup()">
<input type="text" ng-model="group.name">
</form>
<div>
<div ng-if="editGroupModal" class="popup-modal">
<form name="editGroup" ng-submit="saveGroup()">
<input type="text" ng-model="group.name">
<input type="text" ng-model="group.desc">
<input type="text" ng-model="group.id">
</form>
<div>
Controllers.js
WebClientApp.controller('GroupCtrl', function ($scope,$http, $location, $routeParams) {
$scope.group = {};
$scope.showAdd=function(){
$location.path('/groups/add');
}
var template = $routeParams.template;
switch(template){
case 'add':
loadAddPage();
break;
case 'edit':
loadEditPage();
break;
default:
loadListPageHideAll();
break;
}
function loadAddPage() {
$scope.addGroupModal=true;
$scope.editGroupModal=false;
}
function loadEditPage(){
$scope.addGroupModal=false;
$scope.editGroupModal=true;
}
function loadListPageHideAll() {
$scope.addGroupModal=false;
$scope.editGroupModal=false;
// connect to server and list all groups
}
$scope.addandEditGroup = function() {
$location.path('/groups/edit');
}
$scope.saveGroup = function() {
// Save group with $scope.group.
$location.path('/groups');
}
});
When I click on add button, it will show the add form. When I enter group name, and submit, it should show edit form after changing url with the group name filled in the form. But when I try, the value of group object becomes empty since the url is changing. I added the following in controller, but don't know what to do exactly after.
$scope.$on('$routeChangeStart', function(event, present, last) {
console.log(event,present,last);
});
How to assign the scope variables of last route to present route scope. I tried reload on search to false also, But it didnt work.
There might be an error here :
function loadEditPage(){
$scope.addGroupModal=false;
$scope.editGroupModal=true;
}
There are probably some typos in the HTML template code you posted, but what you are basically doing is hiding the parent addGroupModal and showing the child editGroupModal. Remove the nesting and the tags like this:
<div ng-if="addGroupModal" class="popup-modal">
<form name="addGroup" ng-submit="addandEditGroup()">
<input type="text" ng-model="group.name">
</form>
</div>
<div>
<div ng-if="editGroupModal" class="popup-modal">
<form name="editGroup" ng-submit="saveGroup()">
<input type="text" ng-model="group.name">
<input type="text" ng-model="group.desc">
<input type="text" ng-model="group.id">
</form>
</div>
</div>
Here is the plunkr ( hit enter to submit the form): http://plnkr.co/edit/MGT8HZ4lpgVWCkWlt8Ak?p=preview
If this is what you want to acheive, honestly you are complicating things ... There are simpler solutions.
I see! What you want to acheive is to have a reference of the old group variable before the route was changed... And you want to do that using the same controller...
Ok, to get the group from the last controller, you are half way there . You have to store the group somewhere because the targetScopes and currentScopes you receive in the $routeChange listeners don't point to the scopes.
http://plnkr.co/edit/HfK3fhVtZ4bxHtpiFR3B?p=preview
$scope.group = $rootScope.group || {};
$scope.$on('$routeChangeStart', function(event, present, last) {
console.log('start change route');
$rootScope.group = event.currentScope.group;
console.log('target scope group ',event.currentScope.group);
});
I agree the rootScope might not be the best place to keep that variable, but you can also put it inside an angular constant of variable.

Angular JS on keydown get value

I am new to AngularJS, just making a small filter data table. I have a text box, on ng-keydown I am calling a function, in this function I want the value of that textbox.
How can I get it. My code:
HTML:
<body ng-controller="ApplicantsListCtrl">
<input type="text" class="form-control" name="company" ng-model="c" ng-keydown="filter()"></p>
</body>
JS
var app = angular.module('MyApp',[]);
app.controller('ApplicantsListCtrl',['$scope',function($scope){
$scope.filter = function(){
console.log($scope.c);
};
}]);
I am getting undefined in my log.
Is this correct way to do it?
<input type="text" data-ng-change="key(data)" data-ng-model="data"/>
$scope.key = function (data) {
console.log(data);
};
This works.
Rather than keydown, use $watch. See the plunker here
I would use ng-change="filter(c)"

Manual creation of nodes and ng-model

In more attempts to DRY bootstrap and AngularJS, I'm attempting to create a form and children while maintaining the ng-model relationships. I'm getting the correct HTML output, but something isn't connecting correctly with the model relationships, and the model isn't being updated:
Vanilla HTML
<form role="form" ng-model="customer">
<div class="form-group">
<label for="name">Your Name</label>
<input id="name" class="form-control" ng-model="customer.name" />
</div>
</form>
Simplified (goal) HTML
<div abs-form ng-model="customer">
<input id="name" label="Full Name" placeholder="i.e. Joe Smith"/>
</div>
Controller
.controller('HomeCtrl', function($scope){
$scope.customer = {};
}
abs-form Directive
.directive('absForm', function($compile){
var input = $('<input />'),
label = $('<label />');
group = $('<div class="form-group"></div>'),
formElements = [];
return {
restrict : 'EA',
replace : true,
transclude : false,
scope : {
ngModel : '=',
label : "#"
},
compile : function(tElement, tAttrs){
var children = tElement.children();
var tplElement = angular.element('<form role="form" ng-model="'+ tAttrs.ngModel +'" />');
// Clear the HTML from our element
tElement.html('');
// Loop through each child in the template node and create
// a new input, cloning attributes
angular.forEach(children, function(child){
var newInput = input.clone(),
newLabel = label.clone(),
newGroup = group.clone(),
$child = $(child),
attributes = child.attributes;
// Add the "for" attribute and the label text
newLabel.attr('for', $child.attr('id'));
newLabel.text($child.attr('label'));
// Add the class to the input
newInput.addClass('form-control');
newInput.attr('ng-model', tAttrs.ngModel + "." + $child.attr('id'));
// Copy the attributes from the original node to the new one
$.each(attributes, function(index, prop){
newInput.attr(prop.name, prop.value);
})
// Store the form elements for use in link() later
formElements.push(newLabel, newInput)
// Some reason passing in the formElements botches the appending
newGroup.append([newLabel, newInput]);
// Append the group to the element
tplElement.append(newGroup)
})
//$('input', tplElement).wrap('<span>')
// finally, replace it with our tplElement
tElement.replaceWith(tplElement);
}
}
})
This is the output of the directive above, like I said, the HTML is fine (as far as I can tell), but there's no connection of the model:
<form role="form" ng-model="customer" class="ng-pristine ng-valid">
<div class="form-group">
<label for="name">Full Name</label>
<input class="form-control ng-pristine ng-valid" ng-model="customer.name" id="name" label="Full Name" placeholder="i.e. Joe Smith">
</div>
</form>
Some of the questions I've found with similar scenarios (and similar ways to solve)
Changing ngModel
Adding ngModel to input
The second question was the best scenario, but I can't seem to get my new inputs to contribute to the "customer" model. I'm thinking there's more to it than just adding or changing the ng-model attribute on the node, but something Angular is doing to register the connection...?
The problem with your directive is that it introduces an isolate scope which does not include the original model name. The scope variable customer is henceforth known by the name ngModel within the directive's scope.
I updated the code to get rid of the jQuery dependency but basically it still does the same things.
See this fiddle: manual creation of nodes and ng-model

Resources