Manually set the focus on input element in angular js - javascript

I create one input element and on click show the list of items after selecting any item list get hide.
But the focus is not on that element it get down,
So I just want to manually set the focus on input element when radio button list get hide.
Here is use the following code,
View
<label class="item item-input item-stacked-label" ng-click="showDays()">
<span class="input-label black-text">DAYS</span>
<span class="input-ctrl">
<input type="text" id="days" readonly ng-model="data_day" focus-on="!daysflag">
</span>
</label>
<div ng-show="daysflag">
<ion-radio icon="ion-ios-checkmark" ng-model="data_day" ng-value="{{day}}" ng-repeat="day in days" ng-click="hideDayFlag()">{{day}}</ion-radio>
</div>
Controller
$scope.days = [1, 2, 3, 4, 5, 6, 7];
$scope.showDays = function() {
$scope.daysflag = true;
}
$scope.hideDayFlag = function() {
$scope.daysflag = false;
}
Directive
.directive('focusOn',function($timeout) {
return {
restrict : 'A',
link : function($scope,$element,$attr) {
$scope.$watch($attr.focusOn,function(_focusVal) {
$timeout(function() {
_focusVal ? $element[0].focus() :
$element[0].blur();
});
});
}
}
});
Please help me to solve this issue.

You are wrong to use the function scope.$watch. scope.$watch is used to track changes in the $scope.
See detail explanation.
Example on jsfiddle.
angular.module('ExampleApp', [])
.controller('ExampleController', function() {
var vm = this;
vm.isFocus = false;
})
.directive('focusOn', function() {
return {
restrict: 'A',
scope: {
focusOn: "="
},
link: function(scope, $element, $attr) {
scope.$watch('focusOn', function(_focusVal) {
_focusVal ? $element[0].focus() :
$element[0].blur();
});
$element.on("focus", function() {
scope.$applyAsync(function() {
scope.focusOn = true;
});
});
$element.on("blur", function() {
scope.$applyAsync(function() {
scope.focusOn = false;
});
})
}
}
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="ExampleApp">
<div ng-controller="ExampleController as vm">
<input ng-model="vm.countRow" focus-on="vm.isFocus">
<input type="button" value="Focus" ng-click="vm.isFocus=true">
<input type="button" value="Blur" ng-click="vm.isFocus=false">{{vm.isFocus}}
</div>
</div>

Related

Disable AngularJS dropdown multiselect

I have a directive to disable the angularjs dropdown multiselect, this directive working properly when change the checkbox but it's not working when init the control, I want to disable the dropdown by the value that is passed to the directive when start the controller.
that's the directive:
var FormModule = angular.module('FormModule', []);
FormModule.directive('ngDropdownMultiselectDisabled', function () {
return {
restrict: 'A',
controller: function ($scope, $element, $attrs) {
var $btn;
$btn = $element.find('button');
return $scope.$watch($attrs.ngDropdownMultiselectDisabled, function (newVal) {
return $btn.attr('disabled', newVal);
});
}
};
});
and that's the div of the dropdown:
<div class="col-sm-3">
<input id="chkHasParent" type="checkbox" class="form-control"
ng-model="property.HasParent" ng-checked="property.HasParent==true" />
<label for="chkHasParent" class="lblCheck">Has Parent</label>
</div>
<div class="col-sm-3">
<label>Parent Property</label>
<div id="ddlParentProperty" ng-dropdown-multiselect=""
options="Properties" selected-model="parentPropertyModel"
extra-settings="settingParentProperty"
ng-dropdown-multiselect-disabled="!property.HasParent">
</div>
</div>
and thats the docs of the Angular js dropdown multiselect if anyone does not know it.
$scope.hasParentChange = function hasParentChange(hasParent) {
if (hasParent != null) {
if (hasParent == false) {
document.getElementById("ddlParentProperty").getElementsByTagName('button')[0].setAttribute("disabled", "disabled");
}
else {
document.getElementById("ddlParentProperty").getElementsByTagName('button')[0].removeAttribute("disabled");
}
}
else {
document.getElementById("ddlParentProperty").getElementsByTagName('button')[0].setAttribute("disabled", "disabled");
}
}
angular.element(document).ready(function () {
$scope.hasParentChange($scope.property.HasParent)
});

Angular 1 - toggle radio button

I need to make a radio button toggle when user click. Is more then 2 buttons.
So, when I click one button if this is selected will no longer be. If is not must be selected.
I try this, but is not works:
app.directive('toggleRadio', function($timeout) {
return {
restict: 'A',
link: function(scope, el, attrs) {
var radioState;
el.on('click', function(){
if (radioState === this) {
this.checked = false;
radioState = null;
} else {
radioState = this;
}
scope.$apply();
});
}
}
It's not require to be a directive... Thanks.
Since it's a single radio button and as you said It's not required to be a directive, which doesn't seem to be necessary as well, then you can do something like below:
var app = angular.module('app', []);
app.controller('MainCtrl', ['$scope', function($scope) {
$scope.checked = false;
}]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app">
<div ng-controller="MainCtrl">
<input type="radio" ng-model="checked"
ng-value="true" ng-click="checked=!checked" />
{{checked}}
</div>
</div>
Updated:
Ideally, you should use checkboxes for such requirement, but if it so necessary to use radio, then do it like below:
var app = angular.module('app', []);
app.controller('MainCtrl', function($scope) {
$scope.valChanged = false;
$scope.checked = "b";
$scope.toggle = function() {
if (!$scope.valChanged) {
$scope.checked = "";
}
$scope.valChanged = false;
}
});
<script src="https://code.angularjs.org/1.5.2/angular.js"></script>
<div ng-app="app">
<div ng-controller="MainCtrl">
<br>
<input type="radio" ng-model="checked" value="a"
ng-change="valChanged = true" ng-click="toggle()" />Option A
<br>
<input type="radio" ng-model="checked" value="b"
ng-change="valChanged = true" ng-click="toggle()" />Option B
<br>
<input type="radio" ng-model="checked" value="c"
ng-change="valChanged = true" ng-click="toggle()" />Option C
<hr> {{checked}}
</div>
</div>
I choose to create this directive:
myApp.directive('toggleRadio', [function(){
return {
restrict: 'A',
link: function(scope, el, attrs) {
el.on("mouseenter", function(e){
scope.radioStr = e.target.checked;
console.log('scope.radioStr hover: ', scope.radioStr);
});
el.on("click", function(e){
if(scope.radioStr) {
e.target.checked = false;
scope.radioStr = false;
}
else {
e.target.checked = true;
scope.radioStr = true;
}
});
}
}
}]);
And in HTML I have:
With this approach it will works just when user clicks on input itself, not for label. If somebody wants that, must rewrite this directive to find input status with, el.find(), el.next() etc.
Thanks everyone, all your informations help me to understand what've done!

How to bind a value from one ng-model to an other by matching a specific string

I got a requirement to bind a value to a particular model when the value in the other model contains a string starting with "https".
For example, I have two text fields both fields having different model
<input type="text" ng-model="modelText1">
<input type="text" ng-model="modelText2">
Suppose I type a value on the first text field "https", the first input model modelText1 have to bind to the second input model modelText2 and later on i have to maintain it as like two-way binding. i.e. the second field will automatically get the value dynamically when it contains "https" at starting of a string.
Try it like in this Demo fiddle.
View
<div ng-controller="MyCtrl">
<input type="text" ng-model="modelText1">
<input type="text" ng-model="modelText2">
</div>
AngularJS Application
var myApp = angular.module('myApp',[]);
myApp.controller('MyCtrl', function ($scope) {
$scope.modelText1 = '';
$scope.modelText2 = '';
var regEx = new RegExp(/^https/);
$scope.$watch('modelText1', function (newValue) {
if (newValue.toLowerCase().match(regEx)) {
$scope.modelText2 = newValue;
} else {
$scope.modelText2 = '';
}
});
});
An other approach is (that avoid using of $watch) is to use AngularJS ng-change like in this
example fiddle.
View
<div ng-controller="MyCtrl">
<input type="text" ng-model="modelText1" ng-change="change()">
<input type="text" ng-model="modelText2">
</div>
AngularJS Application
var myApp = angular.module('myApp',[]);
myApp.controller('MyCtrl', function ($scope) {
$scope.modelText1 = '';
$scope.modelText2 = '';
var regEx = new RegExp(/^https/);
$scope.change = function () {
if ($scope.modelText1.toLowerCase().match(regEx)) {
$scope.modelText2 = $scope.modelText1;
} else {
$scope.modelText2 = '';
}
};
});
You can use the ng-change directive like this:
<input type="text" ng-model="modelText1" ng-change="onChange()">
<input type="text" ng-model="modelText2">
and your controller:
$scope.onChange = function() {
if ($scope.modelText1 === 'https') {
$scope.modelText2 = $scope.modelText1;
else
$scope.modelText2 = '';
};
use ng-change to check the text is equal to 'https'
angular.module('app',[])
.controller('ctrl',function($scope){
$scope.changeItem = function(item){
$scope.modelText2 = "";
if(item.toLowerCase() === "https"){
$scope.modelText2 = item
}
}
})
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app" ng-controller="ctrl">
<input type="text" ng-model="modelText1" ng-change="changeItem(modelText1)">
<input type="text" ng-model="modelText2">
</div>
EDiTED
to make sure it does't fail under 'HTTPS' use toLoweCase function to make all lower case
HTML :
<input type="text" ng-model="modelText1" ng-change="updateModal(modelText1)">
JS :
var modelText1 = $scope.modelText1.toLowerCase();
$scope.updateModal = function(){
$scope.modelText2 = '';
if(modelText1.indexOf('https')!=-1){
$scope.modelText2 = modelText1;
}
}
you could also possibly do this as a directive if you want to have a more reusable solution over multiple views http://jsfiddle.net/j5ga8vhk/7/
It also keeps the controller more clean, i always try to use the controller only for controlling complex business logic and business data
View
<div ng-controller="MyCtrl">
<input type="text" ng-model="modelText1" >
<input type="text" ng-model="modelText2" model-listener="modelText1" model-listener-value="https" >
</div>
Angular JS
var myApp = angular.module('myApp',[]);
myApp.controller('MyCtrl', function ($scope) {
$scope.modelText1 = '';
$scope.modelText2 = '';
});
myApp.directive('modelListener', [function() {
return {
restrict: 'A',
controller: ['$scope', function($scope) {
}],
link: function($scope, iElement, iAttrs, ctrl) {
$scope.$watch(iAttrs.modelListener, function() {
if($scope[iAttrs.modelListener] === iAttrs.modelListenerValue ) {
$scope[iAttrs.ngModel] = $scope[iAttrs.modelListener];
} else {
$scope[iAttrs.ngModel] = "";
}
}, true);
}
};
}]);

AngularJs Directive get radio button ng-model value on change

I have created an Angular js Directive that loops through ng-repeat and if users chooses any of those radio button, it should alert the current ng-model value.
But its not working. Please help.
var someapp = angular.module('someapp', []);
someapp.controller('someappCtrl', function($scope, $http) {
//...
}).directive('checkthemChoice', function() {
return {
restrict: 'A',
template: '<label ng-repeat="choice in choices" for="{{ choice }}"><input type="radio" ng-checked="$first" name="selecttable" ng-model="radioSelected" value="{{ choice }}" id="{{ choice }}"> {{ choice }}</label>',
link: function(scope, element, attrs) {
scope.choices = ['organization', 'user'];
element.on('change', function() {
//this selected the parent DIV checkthem
//but I want select the radio input inside LABEL
});
scope.$watch('radioSelected', function(val) {
//this doesnt work
alert(val);
});
}
};
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="someapp" ng-controller="someappCtrl">
<div class="checkthem" checkthem-Choice=""></div>
</div>
This works.
radioSelected needs to be a property of an object (for example, test). The explanation is given here https://github.com/angular/angular.js/wiki/Understanding-Scopes
Also, I have a put a test for undefined in the watch to avoid the first alert on load.
var someapp = angular.module('someapp', []);
someapp.controller('someappCtrl', function($scope, $http) {
//...
}).directive('checkthemChoice', function() {
return {
restrict: 'A',
template: '<label ng-repeat="choice in choices" for="{{ choice }}"><input type="radio" ng-checked="$first" name="selecttable" ng-model="test.radioSelected" value="{{ choice }}" id="{{ choice }}"> {{ choice }}</label>',
link: function(scope, element, attrs) {
scope.choices = ['organization', 'user'];
scope.test = {};
element.on('change', function() {
//this selected the parent DIV checkthem
//but I want select the radio input inside LABEL
});
scope.$watch('test.radioSelected', function(val) {
if (val !== undefined) alert(val);
});
}
};
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="someapp" ng-controller="someappCtrl">
<div class="checkthem" checkthem-Choice=""></div>
</div>

$scope missing members for select binding

$scope seems to be missing binding properties for a text box typeahead and a select list.
Here is a fiddle showing the behavior I want: http://jsfiddle.net/langtonr/h4MKa/1/
You can add and remove salesmen as desired. The $scope is binding correctly to $scope.salesmanEntry (the salesman selected in the typeahead) and $scope.selectedSalesmen (salesmen that have been selected in the list box).
This same code I have copied and pasted into my project and it does not work. I am using all the same library references. It seems scope just doesn't work for these 2 variables. $scope.salesmanEntry and $scope.selectedSalesmen are always undefined. My full controller code is below. What could possibly be interfering with my $scope?
I'm outputting the following on my view:
<div>{{salesmanEntry.id}} {{salesmanEntry.displayName}}</div>
My view always shows these correctly, so when I have typed a salesman, it shows up, yet when I get to my controller code, $scope.salesmanEntry is always undefined. It exhibits the same behavior with $scope.selectedSalesmen. I can output to the screen by using an ng-repeat on selectedSalesmen, yet in my controller $scope.selectedSalesmen is always undefined.
manageProductsModule.controller('productDetailCtrl', [
'productSvc', 'equipmentOptionSvc', 'salesmanSvc', '$scope', function (productSvc, equipmentOptionSvc, salesmanSvc, $scope) {
$scope.loadingProduct = false;
$scope.product = {
secureUsers: [],
options: [],
priceHistory: []
};
$scope.addedSalesmen = [];
$scope.allSalesmen = [
{ id: 1, displayName: "Smith, John" },
{ id: 2, displayName: "Ramsey, Gordon" },
{ id: 3, displayName: "White, Betty" }];
$scope.addSalesman = function (salesman) {
if (!salesman.id) return;
var result = $.grep($scope.addedSalesmen, function (e) { return e.id == salesman.id; });
if (result.length === 0) {
$scope.addedSalesmen.push(salesman);
}
$scope.salesmanEntry = { id: -1, displayName: "" };
};
$scope.removeSalesmen = function () {
$scope.selectedSalesmen.forEach(function (salesman) {
var index = $scope.addedSalesmen.indexOf(salesman);
$scope.addedSalesmen.splice(index, 1);
});
$scope.selectedSalesmen = [];
}
}
]);
template:
<div ng-app="manageProductsModule">
<div class="container" ng-controller="productDetailCtrl">
<h3>Model Details</h3>
<form class="form-horizontal" role="form" ng-if="!loadingProduct">
<div class="form-group">
<label for="addSalesmenInput" class="control-label col-md-2">Add</label>
<div class="col-md-4">
<div class="input-group">
<input name="addSalesmenInput"
class="form-control"
ng-model="salesmanEntry"
typeahead="salesman as salesman.displayName for salesman in allSalesmen | filter:$viewValue" />
<div class="input-group-btn">
<button class="btn" ng-click="addSalesman(salesmanEntry)" ng-disabled="!salesmanEntry">
<i class="glyphicon glyphicon-plus"></i>
</button>
</div>
</div>
</div>
</div>
<div class="form-group">
<label for="salesmenInput" class="control-label col-md-2">Salesmen With Access</label>
<div class="col-md-4">
<select name="salesmenInput" multiple="multiple" size="8" class="form-control" ng-model="selectedSalesmen" ng-options="salesman as salesman.displayName for salesman in addedSalesmen"></select>
<button class="btn" ng-click="removeSalesmen()" ng-disabled="!selectedSalesmen || selectedSalesmen.length === 0">
<i class="glyphicon glyphicon-minus"></i>
</button>
</div>
</div>
</form>
</div>
</div>
So here is what I had to do to get this to work. I am definitely not happy with what seems like a very hacky solution and would like to know why this is necessary. I had to go to $scope.$$childHead to access salesmanEntry and selectedSalesmen as they are apparently being stored on the wrong scope.
$scope.addSalesman = function (salesman) {
if (!salesman.id) return;
var result = $.grep($scope.addedSalesmen, function (e) { return e.id == salesman.id; });
if (result.length === 0) {
$scope.addedSalesmen.push(salesman);
}
$scope.$$childHead.salesmanEntry = { id: -1, displayName: "" };
};
$scope.removeSalesmen = function () {
$scope.$$childHead.selectedSalesmen.forEach(function (salesman) {
var index = $scope.addedSalesmen.indexOf(salesman);
$scope.addedSalesmen.splice(index, 1);
});
$scope.$$childHead.selectedSalesmen = [];
}

Categories

Resources