Disable and empty model value and then restore it - angularjs

I have working code:
<input type="checkbox" ng-model="disabled" >
<input type="text" ng-model="text" ng-disabled="disabled">
When disabled == true the input is disabled. I need to hide actual model value (set empty) as well. And after uncheck the checkbox actual model value should appears. How to do it without changing model value?

I would do something like this:
<input type="checkbox" ng-model="disabled" ng-change="change()">
<input type="text" ng-model="text" ng-disabled="disabled">
...
$scope.change = function() {
if ($scope.disabled) {
$scope.textBackup = $scope.text;
$scope.text = '';
} else {
$scope.text = $scope.textBackup;
}
};
Note: I posted before reading #AbdulMateenMohammed comment... My answer is an implementation of his suggestion...

This is not the best option but if you want to deal only with the view:
<input type="checkbox" ng-model="disabled">
<div ng-show="disabled">
<input type="text" ng-init="text2 = ''" ng-model="text2" ng-disabled="true">
</div>
<div ng-hide="disabled">
<input type="text" ng-model="text">
</div>
Again, this is not the best option!!! MarcosS option is the recommended.

#Makarov Sergey, I think even when you have a complex view or data source the basic idea is to use a temporary variable because you need to have two values b/w which you swap around.
angular
.module('demo', [])
.controller('DefaultController', DefaultController);
function DefaultController() {
var originalText = '';
var vm = this;
vm.text = 'Hello, World!';
vm.onValueChanged = onValueChanged;
function onValueChanged(text) {
if (vm.disabled) {
originalText = text;
vm.text = '';
} else {
vm.text = originalText;
}
}
}
span {
color: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div>
<em>I </em><span>♥ </span><em>AngularJS</em>
</div>
<div ng-app="demo">
<div ng-controller="DefaultController as ctrl">
<input type="checkbox" ng-model="ctrl.disabled" ng-change="ctrl.onValueChanged(ctrl.text)"/>
<input type="text" ng-model="ctrl.text" ng-disabled="ctrl.disabled"/>
</div>
</div>
Tip: For the objects that aren't displayed in the view but present in the controller shouldn't be assigned on the scope because using scope would add some JavaScript events to do the data-binding which is unnecessary overhead such as the dirty check event for the two-way data-binding so that's why in the sample code snippet I used var originalText = ''; instead of vm.originalText = '';

Found the solution that works for me atm
function directive() {
return {
restrict: 'A',
require: 'ngModel',
link: function (scope, element, attrs, ngModelCtrl) {
let oldViewValue = '';
scope.$watch(() => attrs.hideValue, (newV) => {
if (newV == 'true') {
oldViewValue = ngModelCtrl.$viewValue;
ngModelCtrl.$viewValue = '';
} else {
ngModelCtrl.$viewValue = oldViewValue;
}
ngModelCtrl.$render();
});
}
}
}
And use:
<input type="checkbox" ng-model="disabled" >
<input type="text" ng-model="text" ng-disabled="disabled" hide-value="disabled">

Related

angularjs directive link function not binding data from Controller

I have a directive that makes use of jquery events on the element parameter of the link function, this directive has an input that is binding to a value that is obtained from the main controller of the page, passed through nested directives in a isolated scope , but when changing the value in the input is not reflected in the original object from controller.
The object has the following structure:
Invoice 1:
- Product 1
- Product 2
Invoice 2:
- Product 3
- Product 4
When I change the amount of the invoice, the value is updated in the main controller, but when I change the amount of the product the change is not reflected.
This is my directive, what you should do is that when the user clicks on the value an input appears to be able to edit the value of the model:
eFieldTemplate.html
<div>
<div ng-if="IsMouseIn">
<input type="text" ng-model="value" class="form-control input-sm" />
</div>
<div ng-if="IsMouseOut" ng-click="OnMouseClick()">
{{value}}
</div>
<div ng-if="MouseClick">
<input type="text" ng-model="value" class="form-control input-sm" />
</div>
eFieldDirective.js
angular.module("appDirectives").directive("eField", function () {
return {
restrict: "E",
templateUrl: "eFieldTemplate.html",
scope: {
value: "="
},
controller: function ($scope) {
$scope.IsMouseOut = true;
$scope.IsMouseIn = false;
$scope.MouseClick = false;
$scope.OnMouseEnter = function () {
if (!$scope.MouseClick) {
$scope.IsMouseOut = false;
$scope.IsMouseIn = true;
$scope.MouseClick = false;
}
}
$scope.OnMouseLeave = function () {
if (!$scope.MouseClick) {
$scope.IsMouseOut = true;
$scope.IsMouseIn = false;
$scope.MouseClick = false;
}
}
$scope.OnMouseClick = function () {
$scope.IsMouseOut = false;
$scope.IsMouseIn = false;
$scope.MouseClick = true;
}
$scope.EndEdit = function () {
$scope.IsMouseOut = true;
$scope.IsMouseIn = false;
$scope.MouseClick = false;
}
},
link: function (scope, el, attrs) {
el.on("mouseenter", function () {
scope.OnMouseEnter();
scope.$apply();
});
el.on("mousemove", function () {
scope.OnMouseEnter();
scope.$apply();
});
el.on("mouseleave", function () {
scope.OnMouseLeave();
scope.$apply();
});
el.on("click", function () {
scope.OnMouseClick();
if (el[0].querySelector('input'))
el[0].querySelector('input').select();
scope.$apply();
});
}
};
});
Any Suggestions?
I give the example here: Plunker
UPDATED
I found a solution using ngIf, and is to reference a variable from the parent scope using $ parent.value. Eg.
<Input type="text" ng-model="$parent.value" class="form-control input-sm" />
Or also referring to another object eg.
<input type="text" ng-model="value">
<div ng-if="IsMouseIn">
<input type="text" ng-model="value">
</div>
Here is the reference link: what is the difference between ng-if and ng-show/ng-hide
using ng-if makes it create/destroy new html nodes and it seems to be unable to cope with that. change to ng-show and it will work. i also added a body mouse capture so it ends the edit.
<div>
<div ng-show="IsMouseIn">
<input type="text" ng-model="value" class="form-control input-sm" />
</div>
<div ng-show="IsMouseOut" ng-click="OnMouseClick()">
{{value}}
</div>
<div ng-show="MouseClick">
<input type="text" ng-model="value" class="form-control input-sm" />
</div>
view plunker
If you want to use ng-if not ng-show still, define $scope.values and $scope.config and use like this. To avoid the ng-if problem you should define an object.
<div>
<div ng-if="config.IsMouseIn">
<input type="text" ng-model="values.value" class="form-control input-sm" />
</div>
<div ng-if="config.IsMouseOut" ng-click="OnMouseClick()">
{{values.value}}
</div>
<div ng-if="config.MouseClick">
<input type="text" ng-model="values.value" class="form-control input-sm" />
</div>

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

How can i write dynamic angularjs directive for validate?

I am newbie in angularjs, and I have a question.
I want to write only a directive for validate all types data (string, number,etc).
I wrote in JSFIDDLE,you can visit here: http://jsfiddle.net/wk8rbot5/5/, it worked.
But I dont want to use if-else to much in this file. I think we can use type or regex from other file. So anyone has suggestion, please let me know. Thank you so much.
var app = angular.module("app",[]);
app.controller("FormCtrl", function($scope) {
$scope.data = {};
$scope.action = function() {
debugger
console.log($scope.data);
}
});
app.directive("allowPattern", function() {
return {
restrict: "A",
require: "ngModel",
link: function(scope, el, attrs, ngModel) {
var validator, patternValidator,
validType = attrs.allowPattern,
required = true;
var pattern = "";
if( validType =="email" ) {
pattern = new RegExp(/^[A-Za-z0-9_-]+([\.]?[A-Za-z0-9_-])*#\w+([-.]\w+)*\.\w+([-.]\w+)*$/);
}
else if(validType =="onlynumber"){
//do other validate here
pattern = new RegExp(/^[0-9]*$/);
} else{
parttern = new RegExp(/^.*S/); // !!! SyntaxError is fixed in this line
}
patternValidator = function(value) {
return validate(pattern, value)
};
ngModel.$formatters.push(patternValidator);
ngModel.$parsers.push(patternValidator);
attrs.$observe("required", function(newval) {
required = newval;
patternValidator(ngModel.$viewValue);
});
function validate(regexp, value) {
if( value == null || value === "" || !required || regexp.test(value) ) { // !!! TypeError: regexp.test is not a function
ngModel.$setValidity('pattern', true);
return value;
}
else {
ngModel.$setValidity('pattern', false);
return;
}
}
}
};
});
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.5.6/angular.min.js"></script>
<div ng-app="app" ng-controller="FormCtrl">
<form name="theForm" novalidate="novalidate">
<input type="text" ng-model="data.name" allow-pattern="email" required/>
<button ng-disabled="theForm.$invalid" ng-click="action()">Action</button>
</form>
<br>
other form:
<br>
<form name="theForm2" novalidate="novalidate">
<input type="text" ng-model="data.number" allow-pattern="onlynumber" required/>
<button ng-disabled="theForm2.$invalid" ng-click="action2()">Action</button>
</form>
<br>
other form 3 :
<br>
<form name="theForm3" novalidate="novalidate">
<input type="text" ng-model="data.abc" allow-pattern="" required/>
<button ng-disabled="theForm3.$invalid" ng-click="action3()">Action</button>
</form>
</div>

Angular watch form input doesnt work

I have a form in html page :
<div ng-controller="ctrl as c">
<form name="myForm">
<input type="text" name="myInput" require/>
</form>
</div>
I want to watch changes of input in my controller, so I did like this :
angular.module('app').controller('ctrl', ctrl);
ctrl.$inject = ['$scope'];
function ctrl($scope) {
var vm = this;
$scope.$watch('myForm.myInput', function (value) {
//check validity
});
}
But when I change input value, nothing happen in controller.
Any idea?
<div ng-controller="ctrl as c">
<form name="myForm">
<input type="text" name="myInput" ng-model="c.myInput" require/>
</form>
</div>
Controller
function ctrl($scope) {
var vm = this;
vm.myInput = 'hello';
$scope.$watch(function(){
return vm.myInput;
}, function(newValue, oldValue) {
console.log(newValue)
});
}
The $scope.watch() function creates a watch of some variable.
So you need to bind a scope to your input and creates watch for that variable.
View:
<input type="text" ng-model="myInput" name="myInput" require/>
Controller:
function ctrl($scope) {
var vm = this;
$scope.myInput = "";
scope.$watch('myInput', function(newValue, oldValue) {
// Your logic
});
}
I believe watching the entire form may create a performance hit, still they are ways to watch multiple variable using watch
1. Create a $scope object like
$scope.form = {
name:"My Name",
Id:"My Id:,
....
}
Now you can use $watch with a third variable 'true'
$scope.$watch('form', function(newVal, oldVal){
console.log('changed');
}, true);
Html:
<input type="text" ng-model="form.name" name="myName" require/>
<input type="text" ng-model="form.id" name="myId" require/>
2. Use $scope.$watchCollection
$scope.$watchCollection('[item1, item2]', function(newValues, oldValues){
// You logic here
// newValues and oldValues contain the new and old value of the array
});
Also check this post for different ways of listening changes to multiple elements using $watch

How to change the placeholder in the textbox by changing checkbox using angular?

I am trying to change the placeholder in the textbox by changing the checkbox using angular. I tried fiddle http://jsfiddle.net/d9uc1dxc/5/.
I have the following code:
**SCRIPT**
function TController($scope) {
$scope.placeholder="%";
$scope.formData = {};
$scope.radioChecked = function ()
{
$scope.placeholder="%";
$scope.apply();
}
$scope.radiounChecked = function ()
{
$scope.placeholder="Count";
$scope.apply();
}
}
What I am trying to achieve is (1) if I change to "%" then the textbox placeholder and (2) if I change to "Count" then the textbox placeholder should change to "Count".
Someone please help me in this issue.
please try to use this code
this is the script file
var app = angular.module("TestApp", []);
function TController($scope) {
$scope.placeholder="%";
$scope.formData = {};
$scope.radioChecked = function ()
{
if($scope.placeholder == "%"){
$scope.placeholder = "Count";
}else{
$scope.placeholder = "%";
}
}
}
and here is the html file
<body ng-app="TestApp" ng-controller="TController">
<div class="flw vreq2">
<label>Voting require2</label>
<div class="oneline">
<div class="onoffswitches">
<input type="checkbox" name="onoffswitch" ng-click="radioChecked()" class="onoffswitch-checkbox" id="myonoffswitch7"/>
<label class="onoffswitch-label" for="myonoffswitch7">
<span class="onoffswitch-inner"></span>
<span class="onoffswitch-switch"></span>
</label>
</div>
</div>
</div>
<div class="per1">
<input type="text" placeholder="{{placeholder}}" ng-model="formData.textInput" />
</div>
</body>
hope you find this useful
you dont need the two functions for checked & unchecked
use ng-change in check box as and add a model to checkbox // model name = onoffswitch
<input type="checkbox" ng-model="onoffswitch" ng-change="radioChecked()" ...
when checkbox checked, onoffswitch model value will be true otherwise false
when changing the checkbox radioChecked() function will invoke
$scope.radioChecked = function ()
{
if($scope.onoffswitch) {
$scope.placeholder="%";
} else {
$scope.placeholder="Count";
}
}
see the demo Plunker

Resources