Enabling checkbox when ng-checked value is False? - angularjs

I have created an checkbox as
<input type="checkbox" name="enableSchedule" ng-model="pr.closed" ng-checked="pr.closed">
Now the condition for "ng-checked="pr.closed" by default evaluates to false as the value of pr.closed is false. but what I want to do is enable the checkbox when the value of pr.closed is false and disbaled when the value is true.
also the ng-model should be updated accordingly i.e if my checkbox is enabled the value of ng-model should be true else false.

You can just negate the ng-checked with negation operator !. But since it is advised not to use ng-model with ng-checked, you can use ng-true-value="false" ng-false-value="true" to trigger the values of your checkbox based on the value of ng-model
<input type="checkbox" name="enableSchedule" ng-model="pr.closed"
ng-true-value="false" ng-false-value="true">
angular.module("App",[])
.controller("ctrl",function($scope){
$scope.pr = {closed:false };
});
<!DOCTYPE html>
<html>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.min.js"></script>
<body ng-app="App" ng-controller="ctrl">
<p>My checkbox:</p>
<input type="checkbox" name="enableSchedule" ng-model="pr.closed"
ng-true-value="false" ng-false-value="true">
Value of ng-model is {{pr.closed}}
</body>
</html>

change the checked="!pr.closed" to check on false.
angular.module("app",[])
.controller("ctrl",function($scope){
$scope.pr = {'closed':false,"modelval" : true }
})
<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="checkbox" name="enableSchedule" ng-model="pr.modelval" ng-checked="!pr.closed">checked value is {{pr.closed}} <br>
model value is {{pr.modelval}}
</div>

angular.module('checklist-model', [])
.directive('checklistModel', ['$parse', '$compile', function($parse, $compile) {
// contains
function contains(arr, item, comparator) {
if (angular.isArray(arr)) {
for (var i = arr.length; i--;) {
if (comparator(arr[i], item)) {
return true;
}
}
}
return false;
}
// add
function add(arr, item, comparator) {
arr = angular.isArray(arr) ? arr : [];
if(!contains(arr, item, comparator)) {
arr.push(item);
}
return arr;
}
// remove
function remove(arr, item, comparator) {
if (angular.isArray(arr)) {
for (var i = arr.length; i--;) {
if (comparator(arr[i], item)) {
arr.splice(i, 1);
break;
}
}
}
return arr;
}
// http://stackoverflow.com/a/19228302/1458162
function postLinkFn(scope, elem, attrs) {
// exclude recursion, but still keep the model
var checklistModel = attrs.checklistModel;
attrs.$set("checklistModel", null);
// compile with `ng-model` pointing to `checked`
$compile(elem)(scope);
attrs.$set("checklistModel", checklistModel);
// getter / setter for original model
var getter = $parse(checklistModel);
var setter = getter.assign;
var checklistChange = $parse(attrs.checklistChange);
var checklistBeforeChange = $parse(attrs.checklistBeforeChange);
// value added to list
var value = attrs.checklistValue ? $parse(attrs.checklistValue)(scope.$parent) : attrs.value;
var comparator = angular.equals;
if (attrs.hasOwnProperty('checklistComparator')){
if (attrs.checklistComparator[0] == '.') {
var comparatorExpression = attrs.checklistComparator.substring(1);
comparator = function (a, b) {
return a[comparatorExpression] === b[comparatorExpression];
};
} else {
comparator = $parse(attrs.checklistComparator)(scope.$parent);
}
}
// watch UI checked change
scope.$watch(attrs.ngModel, function(newValue, oldValue) {
if (newValue === oldValue) {
return;
}
if (checklistBeforeChange && (checklistBeforeChange(scope) === false)) {
scope[attrs.ngModel] = contains(getter(scope.$parent), value, comparator);
return;
}
setValueInChecklistModel(value, newValue);
if (checklistChange) {
checklistChange(scope);
}
});
function setValueInChecklistModel(value, checked) {
var current = getter(scope.$parent);
if (angular.isFunction(setter)) {
if (checked === true) {
setter(scope.$parent, add(current, value, comparator));
} else {
setter(scope.$parent, remove(current, value, comparator));
}
}
}
// declare one function to be used for both $watch functions
function setChecked(newArr, oldArr) {
if (checklistBeforeChange && (checklistBeforeChange(scope) === false)) {
setValueInChecklistModel(value, scope[attrs.ngModel]);
return;
}
scope[attrs.ngModel] = contains(newArr, value, comparator);
}
// watch original model change
// use the faster $watchCollection method if it's available
if (angular.isFunction(scope.$parent.$watchCollection)) {
scope.$parent.$watchCollection(checklistModel, setChecked);
} else {
scope.$parent.$watch(checklistModel, setChecked, true);
}
}
return {
restrict: 'A',
priority: 1000,
terminal: true,
scope: true,
compile: function(tElement, tAttrs) {
if ((tElement[0].tagName !== 'INPUT' || tAttrs.type !== 'checkbox') && (tElement[0].tagName !== 'MD-CHECKBOX') && (!tAttrs.btnCheckbox)) {
throw 'checklist-model should be applied to `input[type="checkbox"]` or `md-checkbox`.';
}
if (!tAttrs.checklistValue && !tAttrs.value) {
throw 'You should provide `value` or `checklist-value`.';
}
// by default ngModel is 'checked', so we set it if not specified
if (!tAttrs.ngModel) {
// local scope var storing individual checkbox model
tAttrs.$set("ngModel", "checked");
}
return postLinkFn;
}
};
}]);
var app = angular.module("app", ["checklist-model"]);
app.controller('Ctrl1', function($scope) {
$scope.roles = [
'guest',
'user',
'customer',
'admin'
];
$scope.user = {
roles: ['user']
};
$scope.checkAll = function() {
$scope.user.roles = angular.copy($scope.roles);
};
$scope.uncheckAll = function() {
$scope.user.roles = [];
};
$scope.checkFirst = function() {
$scope.user.roles.splice(0, $scope.user.roles.length);
$scope.user.roles.push('guest');
};
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app" ng-controller="Ctrl1">
<label ng-repeat="role in roles">
<input type="checkbox" checklist-model="user.roles" checklist-value="role"> {{role}}
</label>
</div>

Related

AngularJS: How to post selected country id and name to asp.net mvc action on button click

i have taken a directive for multi select dropdown from this url http://developers.dss.ucdavis.edu/angularjs-serachable-multiselect-dropdown-directive/
my mvc action give country name and id which i am showing by multiselect dropdown directive and now i like to know if i have a button and when user will click the button then i like to post my all selected countries id and name to mvc action but do not know how to do it in angular.
apologized for posting large code base.
here is my controller code
public class HomeController : Controller
{
public ActionResult MultiSelectCountry()
{
ViewBag.Countries = GetCountries();
return View();
}
[NonAction]
public JsonResult GetCountries()
{
List<Country> oList = new List<Country>()
{
new Country {ID=1,Name="United Kingdom"},
new Country {ID=1,Name="United States"},
new Country {ID=1,Name="Italy"},
new Country {ID=1,Name="Germany"},
new Country {ID=1,Name="India"}
};
return Json(oList);
}
}
my mvc view code
#{
ViewBag.Title = "MultiSelectCountry";
}
<head>
<meta charset="utf-8" />
<title>Serachable Multiselect Directive</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css">
<link rel="stylesheet" href="~/Content/pagestyle.css" />
</head>
#{
Layout = null;
}
<h2>Multi Select Country Demo</h2>
<br /><br /><br /><br /><br />
<body ng-app="app" ng-controller="MainCtrl">
<div class="col-sm-10 col-sm-offset-1">
<searchable-multiselect display-attr="Name"
selected-items="SelectedCountryList" all-items="CountryList"
add-item="addLanguageToUser(item)" remove-item="removeLanguageFromUser(item)" >
</searchable-multiselect>
</div>
<script data-require="jquery" data-semver="2.1.3" src="http://code.jquery.com/jquery-2.1.3.min.js"></script>
<script data-require="bootstrap" data-semver="3.3.2" src="//maxcdn.bootstrapcdn.com/bootstrap/3.3.2/js/bootstrap.min.js"></script>
<script data-require="angular.js#1.3.x" src="https://code.angularjs.org/1.3.14/angular.js" data-semver="1.3.14"></script>
<script data-require="ui-bootstrap" src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-bootstrap/0.13.0/ui-bootstrap-tpls.min.js" data-semver="0.13.0"></script>
<script>
var _countries = #Html.Raw(Json.Encode(ViewBag.Countries));
var app = angular.module('app', ["ui.bootstrap"]);
var yourApp = yourApp || {};
yourApp.Settings = yourApp.Settings || {};
yourApp.Settings.BaseUrl = "#Url.Content("~")";
yourApp.Settings.CountryList = _countries["Data"];
angular.module("app").value("appSettings", yourApp);
</script>
<script src="~/Scripts/app.js"></script>
</body>
app.js code
app.controller('MainCtrl', function ($scope, appSettings) {
$scope.CountryList = appSettings.Settings.CountryList;
$scope.SelectedCountryList = [];
$scope.addLanguageToUser = function (country) {
$scope.SelectedCountryList.push(country)
};
$scope.removeLanguageFromUser = function (country) {
var idx = $scope.SelectedCountryList.indexOf(country);
$scope.SelectedCountryList.splice(idx, 1);
};
});
app.directive("searchableMultiselect", function ($timeout, appSettings) {
return {
templateUrl: appSettings.Settings.BaseUrl + 'Angular/Directives/searchableMultiselect.html',
restrict: 'AE',
scope: {
displayAttr: '#',
selectedItems: '=',
allItems: '=',
readOnly: '=',
addItem: '&',
removeItem: '&'
},
link: function (scope, element, attrs) {
element.bind('click', function (e) {
e.stopPropagation();
});
scope.width = element[0].getBoundingClientRect();
scope.updateSelectedItems = function (obj) {
var selectedObj;
for (i = 0; typeof scope.selectedItems !== 'undefined' && i < scope.selectedItems.length; i++) {
if (scope.selectedItems[i][scope.displayAttr].toUpperCase() === obj[scope.displayAttr].toUpperCase()) {
selectedObj = scope.selectedItems[i];
break;
}
}
if (typeof selectedObj === 'undefined') {
scope.addItem({ item: obj });
} else {
scope.removeItem({ item: selectedObj });
}
};
scope.isItemSelected = function (item) {
if (typeof scope.selectedItems === 'undefined') return false;
var tmpItem;
for (i = 0; i < scope.selectedItems.length; i++) {
tmpItem = scope.selectedItems[i];
if (typeof tmpItem !== 'undefined'
&& typeof tmpItem[scope.displayAttr] !== 'undefined'
&& typeof item[scope.displayAttr] !== 'undefined'
&& tmpItem[scope.displayAttr].toUpperCase() === item[scope.displayAttr].toUpperCase()) {
return true;
}
}
return false;
};
scope.commaDelimitedSelected = function () {
var list = "";
angular.forEach(scope.selectedItems, function (item, index) {
list += item[scope.displayAttr];
if (index < scope.selectedItems.length - 1) list += ', ';
});
return list.length ? list : "Nothing Selected";
}
}
}
});
now suppose i have a button and i want when user click on that button then all selected countries name and id will be posted to mvc action.
i guess some one has to change a bit my directive code because country id is not stored in dropdown. so please help me with code. thanks
Try this (If id/name not included then make a fiddle or code snippet in order to be able to debug)
app.controller('MainCtrl', function ($scope,$http, appSettings) {
$scope.CountryList = appSettings.Settings.CountryList;
$scope.SelectedCountryList = [];
$scope.addLanguageToUser = function (country) {
$scope.SelectedCountryList.push(country)
};
$scope.removeLanguageFromUser = function (country) {
var idx = $scope.SelectedCountryList.indexOf(country);
$scope.SelectedCountryList.splice(idx, 1);
};
//Call on button click
$scope.postData = function()
{
$http({
method: "post",
//Your MVC controller/Action
url: "http://localhost:8080/api/PostCountries",
data:$scope.SelectedCountryList
});
}
});

Decorating a directive by adding a function that will call the directive's controller

I use a directive that is declared like this :
(function (directives) {
var FilterDirective = (function () {
function FilterDirective() {
var directive = {};
directive.restrict = 'A';
directive.scope = true;
directive.controller = elasticui.controllers.FilterController;
directive.link = function (scope, element, attrs, filterCtrl) {
scope.$watch(element.attr('eui-filter') + " | euiCached", function (val) { return scope.filter.filter = val; });
var enabled = false;
var enabledAttr = element.attr('eui-enabled');
if (enabledAttr) {
scope.$watch(enabledAttr, function (val) { return scope.filter.enabled = val; });
enabled = scope.$eval(enabledAttr);
}
scope.filter = {
filter: scope.$eval(element.attr('eui-filter') + " | euiCached"),
enabled: enabled
};
filterCtrl.init();
};
return directive;
}
return FilterDirective;
})();
directives.FilterDirective = FilterDirective;
directives.directives.directive('euiFilter', FilterDirective);
})
The controller of the directive is :
(function (controllers) {
var FilterController = (function () {
function FilterController($scope) {
this.scope = $scope;
}
FilterController.prototype.init = function () {
var _this = this;
if (this.scope.filter.filter) {
var isEnabled = this.scope.filters.contains(this.scope.filter.filter);
if (!isEnabled && this.scope.filter.enabled) {
this.scope.filters.add(this.scope.filter.filter);
isEnabled = true;
}
}
this.scope.filter.enabled = isEnabled;
this.scope.$watch('filter.enabled', function (newVal, oldVal) {
if (newVal !== oldVal) {
_this.updateFilter();
}
});
this.scope.$watch('filter.filter', function (newVal, oldVal) {
if (!elasticui.util.EjsTool.equals(oldVal, newVal)) {
if (oldVal) {
_this.scope.filters.remove(oldVal);
}
_this.updateFilter();
}
});
};
FilterController.prototype.updateFilter = function () {
if (!this.scope.filter.filter) {
return;
}
if (this.scope.filter.enabled) {
this.scope.filters.add(this.scope.filter.filter);
}
else {
this.scope.filters.remove(this.scope.filter.filter);
}
};
FilterController.$inject = ['$scope'];
return FilterController;
})();
controllers.FilterController = FilterController;
})
Actually, the directive has a scope containing a filter object which contains two attributes filter : { enabled : boolean, filter : object} and the directive is used like this :
<label class="btn" ng-model="filter.enabled"
eui-filter="ejs.TermFilter('field','value')" btn-checkbox>
when the button is clicked the filter.enabled is set. My purpose is to add a behavior that will permit to change filter.enabled value via a function external to the directive.
The directive will look like this :
<label class="btn" ng-model="filter.enabled"
eui-filter="ejs.TermFilter('field','value')" eui-enable-fn="fn(somevariable)" btn-checkbox>
where fn will take the somevariable and set it to the filter.enabled.
Thanks in advance,
If you want to enable/disable a filter through the pressure of a button why not declare a filter with the property eui-enabled set to a custom toggling variable?
In other words it would result as:
HTML:
<label class="btn" eui-filter="..." eui-enabled="my_toggling_variable">
<button type=button ng-click="toggleVar()"></button>
JS:
myApp.controller('myCtrl', ['$scope', function($scope) {
$scope.my_toggling_variable = false;
$scope. toggleVar = function(){
$scope.my_toggling_variable = !$scope.my_toggling_variable;
};
}]);
Hope to have understood well the topic.

Focus is not working by index in AngularJS

I have a list of items which have update text field with some words, I want to get the focus at end of the words on the selected index. but every time I am getting focus on last index.
Here is my HTML code
<body ng-controller="MainCtrl">
<h1>Hello Plunker!</h1>
<li ng-repeat="i in number">
<input focus-on="focusMe" value="sfsfsf" />
<button type="submit" ng-click="do()">do</button>
</li>
</body>
Here my controller:
app.directive('focusOn', function() {
return function(scope, elem, attr) {
scope.$on('focusOn', function(e, name) {
if(name === attr.focusOn) {
elem[0].focus();
}
});
};
});
app.factory('focus', function ($rootScope, $timeout) {
return function(name) {
$timeout(function (){
$rootScope.$broadcast('focusOn', name);
});
}
});
app.controller('MainCtrl', function ($scope, focus) {
$scope.number=[1,2,3,4,5,6,7,8,9,10];
$scope.do=function(){
focus('focusMe');
}
Here is my plunker.
Correct solution will probably depend on what browsers you need to support.
You can try this:
scope.$on('focusOn', function(e, name) {
if (name == attr.name) {
var element = elem[0];
element.focus();
var value = element.value;
element.value = '';
element.value = value;
}
});
Demo: http://plnkr.co/edit/pulIrU56qf2J4UjCJlgQ?p=preview

How to find when a specific character is typed in textarea

We have requirement to show a drop down when user enters a "#".
I am planning to have a directive as following:
app.controller('MainCtrl', function($scope) {
$scope.values = ['#'];
$scope.valuesEntered = false;
});
app.directive('identifier', function ($parse) {
return {
scope: {
values: '=values'
},
link: function (scope, elm, attrs) {
elm.bind('keypress', function(e){
var char = String.fromCharCode(e.which||e.charCode||e.keyCode), matches = [];
angular.forEach(scope.values, function(value, key){
if(char === value) matches.push(char);
}, matches);
if(matches.length !== 0){
$scope.valuesEntered = true;
}
});
}
}
});
Will this be ok ?
Here is a simple directive I made that will allow you to specify an expression to evaluate when a given key is pressed or one of an array of keys is pressed.
Note that this is a one-way street. There is currently no going back once you have detected that keypress, even if the user pressed backspace.
var app = angular.module('sample', []);
app.controller('mainCtrl', function($scope) {
$scope.values = ['#', '!'];
$scope.valuesEntered = false;
$scope.valuesEntered2 = false;
});
app.directive('whenKeyPressed', function($parse) {
return {
restrict: 'A',
scope: {
action: '&do'
},
link: function(scope, elm, attrs) {
var charCodesToMatch = [];
attrs.$observe('whenKeyPressed', function(keys) {
if (angular.isArray(keys))
charCodesToMatch = keys.map(function(key) {
if (angular.isString(key))
return key.charCodeAt(0);
});
else if (angular.isString(keys))
charCodesToMatch = keys.split('').map(function(ch) {
return ch.charCodeAt(0);
});
});
elm.bind('keypress', function(e) {
var charCode = e.which || e.charCode || e.keyCode;
if (charCodesToMatch.indexOf(charCode) > -1)
scope.action();
});
}
}
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="sample">
<div ng-controller="mainCtrl">
<p>Values "#" entered? {{valuesEntered}}</p>
<textarea ng-model="str" when-key-pressed="#" do="valuesEntered = true"></textarea>
<p>Values {{values}} entered 2: {{valuesEntered2}}</p>
<textarea ng-model="str2" when-key-pressed="{{values}}" do="valuesEntered2 = true"></textarea>
</div>
</div>
Plunkr demo

Returning hidden object with Angular ng-repeat filter

I am trying to show the first value of a group and hide all other similar values within an ng-repeat. I am getting the if/else to work but it's literally returning "false" as a string. Here is what I have so far.
app.filter('dateSort', function() {
var prevVal = null;
return function(input) {
if (prevVal !== input.uniquedate) {
prevVal = input.uniquedate;
return moment(input.jsdatetime).format('dddd,\n MMMM Do');
} else {
return false;
}
};
});
I've also tried this as a directive, but with no luck.
app.directive('hideon', function() {
var prevVal = $index[-1].uniquedate;
return function(scope, element, attrs) {
scope.$watch(attrs.hideon, function(value, oldValue) {
if(element.uniquedate !== prevVal) {
element.show();
} else {
element.hide();
}
}, true);
}
});
Any help is appreciated. I am assuming that the best way to do this is with a directive. For the filter itself with the returned objects (including the false), the values don't hold after I sort any of the data. That's when I started trying to use it with $watch.
Here's a Codepen with what I've started- http://codepen.io/drewbietron/pen/dKjhe
Here is the fix to blank box display.
app.filter('uniqueDate', function() {
var prevVal = null, prevSeq = null;
return function(input, seq) {
input.show = false;
if (prevVal !== input.month || prevSeq == seq-1) {
prevVal = input.month;
input.show = true;
return input.day + " " + input.month;
}
};
});
Have made code changes to filter the events on selecting types.
var selectedTypes = ["Math", "Science", "Writing"];
$scope.updateSelectedTypes = function(type){
var found = _.some(selectedTypes, function(selType){
return selType == type;
});
if(!found){
selectedTypes.push(type);
}
else{
selectedTypes = _.difference(selectedTypes, type);
}
filterEvents();
};
var filterEvents = function(){
var result = _.filter(Events, function(event){
return _.some(selectedTypes, function(type){
return event.type == type;
});
});
result = _.each(result, function(item){
item.show = false;
});
$scope.events = angular.copy(result);
};
HTML:
<li><b>Filter By:</b></li>
<li class="filter" ng-click="updateSelectedTypes('Math')" ng-class="{ active: Math }">Math</li>
<li class="filter" ng-click="updateSelectedTypes('Science')" ng-class="{ active: Science }">Science</li>
<li class="filter" ng-click="updateSelectedTypes('Writing')" ng-class="{ active: Writing}">Writing</li>
<input type="search" ng-model="instructor.instructor" placeholder="Search By Instructor..." />
Here is the updated codepen link

Resources