Angular JS: how to stop two way binding from happening - angularjs

I have a very simple script that contains angular js
<script>
var delightApp = angular.module('delightmeter', []);
delightApp.controller('delightController', function ($scope) {
$scope.delightScore = 0;
$scope.test = function () {
if (isNaN($scope.delightScore)) {
// do not bind if this happens
}
}
});
</script>
The html of the above script is
<div id="angularapp" data-ng-app="delightmeter" data-ng-controller="delightController">
<input id="Text1" type="text" data-ng-model="delightScore" />
{{delightScore}}
<input id="Button1" type="button" value="button" data-ng-click="test()"/>
</div>
As we know in angular two way binding happens whatever may be the value in $scope.delightScore it gets bound to the html page.
Is there any way to stop this binding from happening ?

Rather than binding to the variable directly, Bind to a function that does your check
<div id="angularapp" data-ng-app="delightmeter" data-ng-controller="delightController">
<input id="Text1" type="text" data-ng-model="delightScore" />
{{ValideDelightScore()}}
<input id="Button1" type="button" value="button" data-ng-click="test()"/>
</div>
And in your controller define:
$scope.ValideDelightScore = function () {
if (isNaN($scope.delightScore)) {
return "";
}else{
return $scope.delightScore
}
}

There is no way to do that because you are explicity binding the model in both scopes. And even if you could you should'n mess with the Angular life-cycle, or you are going to have a bad time.
The right way to achieve what you need is, or using solution purposed by #Shivas Jayaram, or use a filter in where you don't want to display the model if isNaN.
angular.module('myApp.filters', [])
.filter('NaNFilter', function($moment, $translate) {
return function(value) {
if(isNaN(val)) {
return '';
}
return value;
};
});
And in your template:
<div id="angularapp" data-ng-app="delightmeter" data-ng-controller="delightController">
<div>Show delightScore if !NaN: {{delightScore | NaNFilter}}</div>
<input id="Text1" type="text" data-ng-model="delightScore" />
{{delightScore}}
<input id="Button1" type="button" value="button" data-ng-click="test()"/>
</div>

Related

Can I check the condition and change the value of variable in ng-click

ng-click="(document.getElementById('procheck1').checked)?showme=true:showme=false"
(or)
ng-click="if(document.getElementById('procheck1').checked){showme=true;}else{showme=false;}"
Use some function name like this , ng-click="myFunction()" and write whole condition inside that.
myFunction(){
if(document.getElementById('procheck1').checked) {
showme=true;
} else {
showme=false;
}
}
Try this in html page
<div ng-app="MyApp" ng-controller="MyController">
<label for="chkPassport">
<input type="checkbox" id="chkPassport" ng- model="ShowPassport" ng-change="ShowHide()" />
Do you have Passport?
</label>
<hr />
<div ng-show="IsVisible">
Passport Number:
<input type="text" id="txtPassportNumber" />
</div>
</div>
and this part in controller
var app = angular.module('MyApp', [])
app.controller('MyController', function ($scope) {
//This will hide the DIV by default.
$scope.IsVisible = false;
$scope.ShowHide = function () {
//If DIV is visible it will be hidden and vice versa.
$scope.IsVisible = $scope.ShowPassport;
}
});

Select some data and then persist to next controller/view in Angularjs

I am bringing in some simple data via a service that uses angular-resource like so:
angular.module('InvoiceService',
['ngResource'])
.factory('InvoiceService', function ($resource) {
return $resource('data.json');
})
.controller("DashboardListCtrl", function (InvoiceService) {
var vm = this;
InvoiceService.query(function (data) {
vm.invoices = data;
});
vm.submit = function (form) {
console.log(form)
};
});
And the html:
<form name="invoices" role="form" novalidate>
<ul>
<li ng-repeat="invoice in vm.invoices">
<input type="checkbox" id="{{'id-' + $index}}" />
<p><strong>Order:</strong></p>
<p>{{invoice.order}}</p>
</li>
<input type="submit" value="Continue" ng-click="vm.submit(invoices)" />
</ul>
</form>
Everything works fine; the data is displays in the view as expected.
The question:
What I'd like to do is be able to select a checkbox, grab the bit of data associated with that checkbox, and pass it along to the next controller/view on submit. How can I do this?
So, what do I do next? Am I on the right track?
**EDIT: added all angular code to help clarify
Posting answer as reply too big to be useful.
You should be using $scope to isolate the controller's data from the rest of the page.
Read up about ng-model http://docs.angularjs.org/api/ng/directive/ngModel and how to use it to two-way-bind checkbox value to a controller variable. No need to use theFormName if you call $scope.submit = function() { } as your ng-model variable will be available in $scope already.
angular.module('InvoiceService',
['ngResource'])
.factory('InvoiceService', function ($resource) {
return $resource('data.json');
})
.controller("DashboardListCtrl", function ($scope, InvoiceService) {
InvoiceService.query(function (data) {
$scope.invoices = data;
});
$scope.submit = function () {
// FIXME to access a property of each $scope.invoices
console.log('checkbox1=' + $scope.invoices[0].checkbox1);
};
});
Then the HTML:
<form role="form" novalidate ng-controller="DashboardListCtrl"><!-- EDIT: added ng-controller=, remove name= -->
<ul>
<li ng-repeat="invoice in invoices"><!-- EDIT: remove 'vm.' -->
<input type="checkbox" id="{{'id-' + $index}}" ng-model="invoice.checkbox1" /><!-- EDIT: added ng-model= -->
<p><strong>Order:</strong></p>
<p>{{invoice.order}}</p>
</li>
<input type="submit" value="Continue" ng-click="submit()" /><!-- EDIT: remove 'vm.' -->
</ul>
</form>

Is there a better way to gather angular form data (for submit)

this is my solution, but I do not know if it is the right way.
html:
<div ng-controller='myctrl as mc'>
<form name='mc.form' ng-submit='mc.submit'>
<input type='email' name='email' />
<input type='user' name='user' />
<button type='submit'>submit</button>
</form>
</div>
javascript:
angular.module('myapp').controller('myctrl', ['$scope', function myctrl($scope) {
var th = this
this.submit = function(form) {
if(!th.form.$invalid) postToServer(getFormData())
}
//I checked the form object, no helper method like this
function getFormData() {
var res = {}
angular.forEach(th.form, function(value, key) {
if(key[0] !== '$') res[key] = value.$modelValue
})
return res
}
function postToServer(data) {
//do post to server
console.log(data)
}
}])
This is an example of basic Angular Forms usage. You want to use ng-modal and within your Controller $scope you should have a Object for your form data that you will be processing. If you give the form a name attribute, it will bind this to your Controller $scope so that you can access within your controller, for example <form name="myForm"> == $scope.myForm.
Please find this live example below, if you open your Console F12 menu you will see the form data when it is submitted.
http://plnkr.co/edit/XSiPnDdB5umxOzu0V3Pf?p=preview
<form name="myForm" ng-submit="submitForm()">
Email: <input name="email" type="email" ng-model="formData.email" />
<br />
User: <input name="user" type="text" ng-model="formData.user" />
<br />
<button type="submit">Submit</button>
</form>
<script>
angular.module('myApp', [])
.controller('mainCtrl', function($scope) {
$scope.formData = {};
$scope.submitForm = function() {
// do form submit logic
// this is the object declared in the controller
// binded with ng-model
console.log('$scope.formData');
console.log($scope.formData);
// this is the ng-form $scope binded into
// the Controller via <form name="name">
// this hold more that just the form data
// validation errors form example
console.log('$scope.myForm');
console.log($scope.myForm);
};
});
</script>
You should use ng-model, it will all the form data will be sent as an object
<div ng-controller='myctrl as mc'>
<form name='mc.form' ng-submit='mc.submit'>
<input ng-model='formData.email' name='email' />
<input ng-model='formData.user' name='user' />
<button type='submit'>submit</button>
</form>
</div>
The input value will bind to the properties of an object call formData in controller
angular.module('myapp').controller('myctrl', ['$scope',
function myctrl($scope) {
var th = this;
$scope.formData= {}; //Initialise the object
this.submit = function(form) {
if (!th.form.$invalid) postToServer();
}
function postToServer() {
//do post to server
console.log($scope.formData); //The value of input will bind to the property of formData
}
}
])

What is wrong in this binding?

I have an angular ui-grid in which data is displayed and in every row there is an "Edit" and "Delete" button. When the user clicks on the "Edit" then a modal window is displayed and the fields are populated and the user can edit the data. This is the user scenario I have. When the user clicks on the "Edit" button I pass through the id value and when angular creates the modal window I query the data from the server.
As you can see in the html the controller is not bound because it is managed by another controller. If it would be bound here then it would be called twice.
The fields are populated properly and when I change something in it and I want to save it then breeze says that nothing has changed in the entity and the log in the save method gives back the original values of the entity.
I assume something is wrong with the data binding but I don't know what.
According to the pluralsight video and breeze's documentation breeze tracks the changes in the entity.
What I'm doing wrong?
The form:
<form class="form-horizontal" name="editModuleModalForm">
<legend>Edit module</legend>
<div class="control-group">
<label class="control-label">Module name</label>
<div class="controls">
<input type="text"
placeholder="Module name here..."
data-ng-model="vm.sysmodule.name"
data-z-validate />
</div>
</div>
<div class="control-group">
<label class="control-label">Module Sort number</label>
<div class="controls">
<input type="text"
placeholder="Module sort number"
data-ng-model="vm.sysmodule.sortNo"
data-z-validate />
</div>
</div>
<div class="control-group">
<label class="control-label">Route</label>
<div class="controls">
<input type="text"
placeholder="Module route comes here..."
data-ng-model="vm.sysmodule.route"
value="vm.sysmodule.route"
data-z-validate />
</div>
</div>
<div class="control-group">
<button type="submit" class="btn btn-success" data-ng-click="vm.save()">Save</button>
<button type="submit" class="btn btn-danger" data-ng-click="vm.cancel()">Cancel</button>
</div>
</form>
Angular controller for the form
(function () {
'use strict';
var controllerId = 'editModuleController';
angular
.module('dilibApp')
.controller(controllerId, ['$scope', '$modalInstance', 'selectedModuleId', 'common', 'datacontext', editModuleController]);
function editModuleController($scope, $modalInstance, selectedModuleId, common, datacontext) {
/* jshint validthis:true */
var vm = this;
vm.title = 'editModule';
vm.sysmodule = undefined;
vm.cancel = cancel;
vm.save = save;
activate();
function activate() {
onDestroy();
common.activateController([getModulePropertiesToBeEdited()], controllerId);
}
function getModulePropertiesToBeEdited() {
return datacontext.sysmodule.getById(selectedModuleId)
.then(function (result) {
vm.sysmodule = result[0];
});
}
function onDestroy() {
$scope.$on('$destroy', function () {
datacontext.cancel();
});
}
function cancel() {
$modalInstance.dismiss('cancel');
}
function save() {
console.log(vm.sysmodule);
if (datacontext.hasChanges) {
datacontext.saveChanges();
console.log('Changes are saved!');
} else {
console.log('There are no changes to be saved!');
}
$modalInstance.close();
}
}
})();
Nothing is wrong with the binding. The root if the problem is that the datacontext doesn't have hasChanges method due to that the breeze's entityManager is wrapped in it. I had to rework the code a little bit, rethinking the responsibilities and it is working now.

Unable to submit data via form

I have a simple form:
<form ng-submit='addMessage()'>
<input type='text' ng-model='chatMessage' placeholder='chat here' />
<input type='submit' value='chat' />
</form>
And at the moment, a very simple function:
$scope.addMessage = function() {
console.log($scope.chatMessage);
}
The console logging is just logging undefined, no matter what I type into the input box. Clearly I'm missing something, but I'm not sure what that is.
Depending on the way forms are used, sometimes $scope is out of context between the controller on the form. This is because addMessage(), and chatMessage are not on the same level of the $scope hierarchy.
One way to fix this is to create a container for your form items:
$scope.cont = {};
$scope.addMessage = function() {
console.log($scope.cont.chatMessage);
}
And in the form:
<input type="text" ng-model="cont.chatMessage" placeholder="chat here"/>
This is also something you should definitely read if you are going to use angular more: http://jimhoskins.com/2012/12/14/nested-scopes-in-angularjs.html
Look for that fiddle maybe you missed something different .
<div ng-app="app">
<div ng-controller="mainCtrl">
<form ng-submit='addMessage()'>
<input type='text' ng-model='chatMessage' placeholder='chat here' />
<input type='submit' value='chat' />
</form>
<pre>{{msg | json}}</pre>
</div>
</div>
JS:
var app = angular.module("app", []);
app.controller("mainCtrl", function ($scope) {
$scope.msg = [];
$scope.addMessage = function () {
$scope.msg.push($scope.chatMessage);
console.log($scope.chatMessage);
$scope.chatMessage = "";
}
});
This should work:
<form ng-submit='addMessage(chatMessage)'>
<input type='text' ng-model='chatMessage' placeholder='chat here' />
<input type='submit' value='chat' />
</form>
And in your controller:
$scope.addMessage = function(msg) {
console.log(msg);
}
UPDATE
based on your comments i think you are looking for something like this:
$scope.messages = [];
$scope.$watch('messages', function(newMessage) {
alert('hey, a message was added ! :' +newMessage);
}, true);
$scope.addMessage = function(msg) {
$scope.messages.push(msg);
};
Angular has so called watches, the watched function will trigger everytime when a new message is addded to the array. For more information about watches refer to the docs

Resources