how to change ng-class on conditions? - angularjs

I have a label that has class value based on 3 different conditions.
status = true => domain available
status =false=> domain not available
click => domain is selected
but when click on it, class should change to 'check-yes1'. How can i make it to change cssClass when clicked?
<div ng-repeat="(key,value) in newReg.checkedDomains | groupBy: 'domain'">
<label class="checkbox-inline" ng-class="{'check-yes' : ext.status==true}" ng-repeat="ext in value">
<input type="checkbox">
</label>
</div>
i even tried something like
<label class="checkbox-inline" ng-click="updateSelectStatus(ext.status,true)" ng-class="updateSelectStatus(ext.status,false)" ng-repeat="ext in value">
<input type="checkbox">
</label>
$scope.updateSelectStatus = function (status, selected) {
if (selected) {
return 'checked';
}
return status == 'true' ? 'check-yes' : '';
}
sorry to confuse with the mess :)

Full example:
<!doctype html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.0/angular.js"></script>
<style>
.check-yes {
background-color: green;
}
.available {
background-color: yellow;
}
.not-available {
background-color: red;
}
</style>
</head>
<body ng-app="plunker">
<div ng-controller="MainCtrl">
<div ng-repeat="(key,value) in newReg.checkedDomains">
<label class="checkbox-inline"
ng-class="{'check-yes': ext.available && ext.status,
'available': ext.available && !ext.status,
'not-available': !ext.available}"
ng-repeat="ext in value">
{{ext.name}} <input type="checkbox" ng-model="ext.status" ng-disabled="!ext.available">
</label>
</div>
</div>
<script>
var app = angular.module('plunker', []);
app.controller('MainCtrl', ['$scope', function($scope) {
$scope.newReg = {checkedDomains:
[
[{
status: true,
available: true,
name: 'com'
},{
status: false,
available: false,
name: 'org'
}],
[{
status: false,
available: true,
name: 'net'
},{
status: false,
available: true,
name: 'biz'
}]
]
};
}]);
</script>
</body>
</html>

Instead of binding to a function, use model.
<label class="checkbox-inline" ng-class="{'check-yes' : ext.status}" ng-repeat="ext in value">
<input type="checkbox" ng-model='ext.status'/>
</label>

Related

AngularJS Email Validation

I am trying to show Email valid messages using below code but problem is email error message not showing in red color. How can I resolve this problem?
https://codepen.io/rama-krishna-the-selector/pen/PXOwQp?editors=1010
.html
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u"
crossorigin="anonymous">
<!-- JAVA SCRIPT REFERENCES -->
<script src="https://code.jquery.com/jquery-3.1.1.min.js" integrity="sha256-hVVnYaiADRTO2PzUGmuLJr8BLUSjGIZsDYGmIJLv2b8="
crossorigin="anonymous"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa"
crossorigin="anonymous"></script>
<script src="https://code.angularjs.org/1.3.0-beta.5/angular.js"></script>
<script src="app.js"></script>
</head>
<body ng-app="plunker" >
<div ng-controller="DynamicFormController">
<h3>Dynamic Radio Buttons</h3>
<form name="myForm" class="form-horizontal" role="form" ng-submit="submitForm()">
<div ng-repeat="field in entity.fields">
<ng-form name="form">
<!-- EMAIL FIELDS -->
<div ng-if="field.type=='email'" class="form-group" ng-class="{ 'has-error' :
form[field.name].$dirty && form[field.name].$error.required,
'has-success': form[field.name].$valid}">
<label class="col-sm-2 control-label">{{field.label}}</label>
<div class="col-sm-6">
<input type="{{ field.type }}" dynamic-name="field.name" id="{{field.name}}" ng-model="field.data"
class="form-control" required />
<p class="help-block" ng-show="form[field.name].$dirty && form[field.name].$error.required">{{field.name}}
is required</p>
<p class="help-block" ng-show="form[field.name].$dirty && form[field.name].$error.email">Please enter valid {{field.name}}</p>
<!-- <p class="help-block" ng-show="{{'form.'+field.name+'.$dirty && form.'+field.name+'.$error.required'}}">required</p> -->
</div>
</div>
</ng-form>
</div>
<br/>
<button ng-disabled="myForm.$invalid" type="submit" id="submit">Submit</button>
<br/>
<pre>{{entity|json}}</pre>
<br/>
</form>
</div>
</body>
</html>
.js
var app = angular.module('plunker',[]);
app.controller('DynamicFormController', function ($scope, $log) {
// we would get this from the api
$scope.entity = {
name : "Course",
fields :
[
{type: "text", name: "firstname", label: "Name" , required: true, data:""},
{type: "radio", name: "color_id", label: "Colors" , options:[{id: 1, name: "orange"},{id: 2, name: "pink"},{id: 3, name: "gray"},{id: 4, name: "cyan"}], required: true, data:""},
{type: "email", name: "emailUser", label: "Email" , required: true, data:""},
{type: "text", name: "city", label: "City" , required: true, data:""},
{type: "password", name: "pass", label: "Password" , min: 6, max:20, required: true, data:""},
{type: "select", name: "teacher_id", label: "Teacher" , options:[{name: "Mark"},{name: "Claire"},{name: "Daniel"},{name: "Gary"}], required: true, data:""},
{type: "checkbox", name: "car_id", label: "Cars" , options:[{id: 1, name: "bmw"},{id: 2, name: "audi"},{id: 3, name: "porche"},{id: 4, name: "jaguar"}], required: true, data:""}
]
};
$scope.submitForm = function(){
$log.debug($scope.entity);
}
})
.directive("dynamicName",function($compile){
return {
restrict:"A",
terminal:true,
priority:1000,
link:function(scope,element,attrs){
element.attr('name', scope.$eval(attrs.dynamicName));
element.removeAttr("dynamic-name");
$compile(element)(scope);
}
}
})
Well you can add a class like this:
ng-class="{'has-error': form[field.name].$error.email }"
So your element will change to :
<p class="help-block has-error" ng-class="{'has-error': form[field.name].$error.email }" ng-show="form[field.name].$dirty && form[field.name].$error.email">Please enter valid {{field.name}}</p>
And to your classes you can add a error class like this:
.has-error
{
color:red !important;
}
Update HTML with following directive with condition in tag at message Please enter valid {{field.name}}
ng-class="{'red':form[field.name].$error.email}"
add CSS class
.red{color:#ff0000;}
!important is not required in this case

Angular setting default radio selection in ng-repeat

I am presenting a simple yes/no answer question to my users and I want to have a default radio button selected. The problem is that I could have any number of these questions presented to the user.
This is my code:
<div ng-form ng-repeat="i in offers track by $index" name="messageForm[$index]">
<div data-ng-repeat="option in closeListingOptions" class="radio">
<label>
<input type="radio" name="close" ng-model="i.close" value="{{option.id}}" ng-checked="option.checked" />{{option.name}}</strong>
</label>
</div>
</div>
My options are set as follows:
$scope.closeListingOptions = [
{
id: "1",
name: "Yes please",
checked: true
},
{
id: "0",
name: "No thanks",
checked: false
}
];
The above example works and check/sets "yes" as the default answer. However unless I manually select an option via a mouse click the value is not binding to the model.
I have read that ng-select should not be used with ng-options but i am not sure how else I can achieve this goal? It seems that I need something like:
i.close = "1":
But how can I set this for an unknown quntity since I don't know how many question will be presented?
1- Instead of value={{something}} you can use ng-value directive.
2- Each input pack should have its specific name.
Here is a working example:
var app = angular.module("app", []);
app.controller("MainCtrl", function($scope) {
$scope.offers = [{
number: 1
},
{
number: 2
}
];
$scope.closeListingOptions = [{
id: "1",
name: "Yes please",
checked: true
},
{
id: "0",
name: "No thanks",
checked: false
}
];
});
<html ng-app="app">
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
</head>
<body ng-controller="MainCtrl">
<div ng-form ng-repeat="i in offers" name="messageForm[$index]">
<div data-ng-repeat="option in closeListingOptions" class="radio">
<label>
<input type="radio" name="close-{{i.number}}" ng-model="i.close" ng-value="option.id" ng-checked="option.checked" />{{option.name}}</strong>
</label>
</div>
{{i}}
<hr>
</div>
</body>
</html>
You should try this:
<input type="radio" name="close"
ng-model="option.checked" value="{{option.id}}"
ng-checked="option.checked" />{{option.name}}</strong>
This ng-model will updated the checked key of your data array and then you can fetch all the radio button selection as per their ids from that single variable.
Hope this helps.
I was able t achieve my goal with the following:
<div data-ng-repeat="option in closeListingOptions" class="radio" ng-init="i.closeListing = 1">
<label>
<input type="radio" name="close-{{i.id}}" ng-model="i.closeListing" ng-value="{{option.id}}" />
<strong>{{option.name}}</strong>
</label>
</div>
The solution was to use ng-init

make JSON array from dynamic form data angular

i have a dynamic form in angular. and i want to send the response as json. how do i generate JSON from the form?
here's the complete code,I have to get json, and post it to some api.
<!DOCTYPE html>
<html>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
<body>
<div ng-app="myApp" ng-controller="dyf" ng-submit="submit()">
<form name="userFormOne" novalidate>
<table>
<tr class="form-group" ng-repeat="x in names">
<td><label>{{ x.Field }}</label>
</td><td><input type="text" class="form-control" placeholder="{{x.Comment}}" required>
</td>
</tr>
</table>{{data}}
</form>
</div>
<script>
var app = angular.module('myApp', []);
app.controller('dyf', function($scope, $http) {
$http.get("http://localhost:5000/gu")
.then(function (response) {$scope.names = response.data;console.log(response.data);});
$scope.data ={};
});
</script>
</body>
</html>
In AngularJs we use ng-model to bind inputs value to our controller, sample:
This full sample to figure out how to create a simple form, from array and how to send it as JSON to your API.
Note: On submit check your console, and see the objects value.
var app = angular.module("app", []);
app.controller("ctrl",
function ($scope) {
var options = [
{ name: "a" },
{ name: "b" },
{ name: "c" }
];
$scope.names = [
{ id: 1, field: "insert name", name: "name", placeholder: "your name is", value:null, type:"text" },
{ id: 2, field: "insert phone", name: "phone", placeholder: "your phone is", value: null, type: "tel" },
{ id: 3, field: "insert age", name: "age", placeholder: "your age is", value: null, type: "number", min: 0, max: 20 },
{ id: 4, field: "select country", name: "country", placeholder: "your country is", value: null, type: "select", options: options }
];
$scope.sendMe = function() {
console.log($scope.names);
}
});
<!DOCTYPE html>
<html ng-app="app" ng-controller="ctrl">
<head>
<title></title>
<meta charset="utf-8" />
</head>
<body>
<form name="userFormOne" novalidate>
<table>
<tr class="form-group" ng-repeat="x in names">
<td>
<label>{{ x.field }}</label>
</td>
<td ng-if="x.type != 'select'">
<input type="{{x.type}}" min="{{x.min}}" max="{{x.max}}" ng-model="x.value" name="{{x.name}}" placeholder="{{x.placeholder}}" ng-required="true">
{{x.value}}
</td>
<td ng-if="x.type == 'select'">
<select ng-model="x.value" name="{{x.name}}" ng-options="item as item.name for item in x.options">
</select>
{{x.value}}
</td>
</tr>
</table>
<button ng-disabled="userFormOne.$invalid" ng-click="sendMe()">sendMe</button>
</form>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
</body>
</html>

Adding the input fields dynamically from nested json object in angulajs

var inputs={
'firstname': '',
'lastName':'',
'account':{
'role':'',
'status':''
}
}
This is my model array. I want to display it dynamically in Webpage and by modifying the json array the changes should affect the form too.
Here is the image
UPD:
for your situation, you can use ng-switch to generate elements according to conditions.
Notice(already included in the code snippet):
ng-repeat will generate it's own scope, so your model won't update unless you bind it with the original scope. ref here.
OLD ANSWER:
use ng-model to implement two-way-databinding.
refer the code snippet below:
angular.module("app", []).controller("myCtrl", function($scope) {
$scope.inputs = {
'firstname': 'test first name',
'lastName': 'test last name',
'account': {
'role': 'test role',
'status': 'test status'
}
};
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.4/angular.min.js"></script>
<div ng-app="app" ng-controller="myCtrl">
<!-- First Name: <input type="text" ng-model="inputs.firstname"><br>
Last Name: <input type="text" ng-model="inputs.lastName"><br> Account Role: <input type="text" ng-model="inputs.account.role"><br>
Account Status: <input type="text" ng-model="inputs.account.status"><br> -->
<div ng-repeat="(key1, value) in inputs" ng-switch="key1">
<div ng-switch-when="account">
<div ng-repeat="(key2, value2) in value">
{{key1 | uppercase}} => {{ key2 | uppercase}}
<input type="text" ng-model="inputs[key1][key2]">
</div>
</div>
<div ng-switch-default>
{{key1 | uppercase}}
<input type="text" ng-model="inputs[key1]">
</div>
</div>
{{inputs}}
</div>
/My html should look like this/
<head>
<script data-require="angular.js#1.4.1" data-semver="1.4.1" src="https://code.angularjs.org/1.4.1/angular.js"></script>
<script src="script.js"></script>
</head>
<body ng-controller="MainCtrl">
<script type="text/ng-template" id="tree-structure">
<label>{{dt}}</label><input type="text" name="" value="{{dt.label}}">
<ul class="childElement">
<li ng-repeat="dt in dt.nodes" ng-include="'tree-structure'">
</li>
</ul>
</script>
<ul class="parentList">
<li ng-repeat="(key, value) in inputs" >
<div ng-repeat="(key1, value1) in value">
<label>{{key1}}</label>
<input type="text" name="" value="{{value1}}">
<!-- <div ng-repeat="(key2, value2) in value1">
<label>{{key2}}</label><input type="text" name="" value="{{value2}}">
</div> -->
</div>
<div ></div>
</li>
</div>
</ul>
</body>
</html>
Some observations :
Your JSON should be formatted properly with type of the field.
If you want to access the object properties as a form fields then it should be structured in a good way so that we can dynamically add the type of the field as well.
[{
name: 'firstName',
type: 'text'
}, {
name: 'lastname',
type: 'text'
}, {
account: [{
name: 'role',
type: 'text'
}, {
name: 'status',
type: 'text'
}]
}]
As your JSON have nested objects. So, first iterate it recursively and create one dimensional array then create the fields using 1D array.
DEMO
var myApp = angular.module('myApp',[]);
myApp.controller('MyCtrl', function($scope) {
var inputs = [{
name: 'firstName',
type: 'text'
}, {
name: 'lastname',
type: 'text'
}, {
account: [{
name: 'role',
type: 'text'
}, {
name: 'status',
type: 'text'
}]
}];
$scope.fields = [];
function structuredObj(obj) {
for (var i in obj) {
if (obj[i].type == 'text') {
$scope.fields.push(obj[i]);
} else {
structuredObj(obj[i])
}
}
};
structuredObj(inputs);
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myApp" ng-controller="MyCtrl">
<form name="myForm" novalidate>
<div ng-repeat="item in fields" class="form-group">
<input
name="item.name"
type="{{ item.type }}"
placeholder="{{ item.name }}"
ng-model="item.value"
required />
</div>
<button ng-disabled="myForm.$invalid">Submit</button>
</form>
</div>
<div ng-repeat="(key1, value1) in myPersonObj">
<div ng-repeat="(key, value) in value1">
<label>{{key}}</label>
<input type="text" name="" value="{{value}}">
</div>
</div>
var app = angular.module("test",[]);
app.controller("MainCtrl",function($scope){
$scope.inputs = [
{
"firstname" : "Test"
},{
"lastname" : "Test1"
},{
"Account" : [
{"role" : "Test3"},
{"status" : "Test4"},
]
},
{
"Account1" : [
{"role" : "Test3"},
{"status" : "Test4"},
]
},
{
"Account2" : [
{"role" : {
'dim3': {
'dim4':{
'dim5':'cccc'
}
}
}
},
{"status" : "Test4"},
]
}
];
$scope.person = [];
$scope.myPersonObj = [];
/*console.log($scope.keys(inputs));*/
$scope.checkIndex1 = function(arg, myPersonObj)
{
if (angular.isArray(arg) || angular.isObject(arg)) {
angular.forEach(arg, function (value, key) {
console.log(value);
if(angular.isObject(value) || angular.isArray(value))
{
$scope.checkIndex1(value, myPersonObj);
}
else
{
console.log("pushing");
myPersonObj.push(arg);
}
});
}
else
{
console.log("pushing1");
myPersonObj.push(arg);
}
}
$scope.checkIndex1($scope.inputs, $scope.myPersonObj);
console.log("myPersonObj :"+ JSON.stringify($scope.myPersonObj));
console.log($scope.inputs);

How to set default value in each cascading dropdown using angular?

I have the dropdown as demonstrated below. All of this work. I just need to set default value for each one. I know how to do it for the upper level but how to do it for the next levels?
This is my html code:
<html ng-app="plunker">
<head>
<meta charset="utf-8" />
<title>AngularJS Plunker</title>
<script data-require="angular.js#1.2.x" src="https://code.angularjs.org/1.2.20/angular.js" data-semver="1.2.20"></script>
<script src="app.js"></script>
</head>
<body ng-controller="MainCtrl">
<div class="row">
<div class="col-md-4 col-xs-4 col-sm-4">
<select required ng-change="onBookChange(books,book)" ng-model="book" ng-options="bb.bookName for bb in books" class="form-control" >
<option value="">--Select--</option>
</select>
</div>
<div class="col-md-4 col-xs-4 col-sm-4">
<select required ng-model="chapter" ng-change="onChapterChange(books,chapter)" ng-options="cha.chapterName for cha in books.selectedChapters" class="form-control" >
<option value="">--Select--</option>
</select>
</div>
<div class="col-md-4 col-xs-4 col-sm-4">
<select required ng-model="title" ng-change="onTitleChange(books,title)" ng-options="t for t in books.selectedTitles" class="form-control" >
<option value="">--Select--</option>
</select>
</div>
</div>
</body>
</html>
and this is my javascript code:
var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope) {
$scope.books=[
{
id:1,
bookName:'C++',
chapter:[
{chapterName:'Introduction',titles:['About Author','C++ Basic']},
{chapterName:'OOPS basic',titles:['Class','Object','Data Encapsulation','Inheritance','Interface']},
]
},
{
id:2,
bookName:'Java',
chapter:[
{chapterName:'Java Introduction',titles:['About Author','Java Intro']},
{chapterName:'Java basic',titles:['Variables','Function','Function Overloading','Class','Object']},
]
},
{
id:3,
bookName:'Angular JS',
chapter:[
{chapterName:'Introduction',titles:['MVC','Model','View','Controller']},
{chapterName:'Key Features',titles:['Template','Scope','Expressions','Filter','Controller','Module']},
]
}
];
$scope.onBookChange=function(b,book){
//alert("inside");
b.selectedChapters=book.chapter;
}
$scope.onChapterChange=function(b,cha){
//alert("inside");
// console.log(cha);
b.selectedChapter=cha;
b.selectedTitles=cha.titles;
}
$scope.onTitleChange=function(b,t){
// alert(t);
b.selectedTitle=t;
}
});
Please see demo below
var app = angular.module('app', ['ui.bootstrap']);
app.controller('homeCtrl', function($scope) {
$scope.books = [
{
id: 1,
bookName: 'C++',
chapter: [{
chapterName: 'Introduction',
titles: ['About Author', 'C++ Basic']
}, {
chapterName: 'OOPS basic',
titles: ['Class', 'Object', 'Data Encapsulation', 'Inheritance', 'Interface']
},
]
}, {
id: 2,
bookName: 'Java',
chapter: [{
chapterName: 'Java Introduction',
titles: ['About Author', 'Java Intro']
}, {
chapterName: 'Java basic',
titles: ['Variables', 'Function', 'Function Overloading', 'Class', 'Object']
},
]
}, {
id: 3,
bookName: 'Angular JS',
chapter: [{
chapterName: 'Introduction',
titles: ['MVC', 'Model', 'View', 'Controller']
}, {
chapterName: 'Key Features',
titles: ['Template', 'Scope', 'Expressions', 'Filter', 'Controller', 'Module']
},
]
}
];
$scope.onBookChange = function(b, book) {
//set default chapter
$scope.chapter = book.chapter[0];
//set default title
$scope.title = $scope.chapter.titles[0];
}
$scope.onChapterChange = function(b, chapter) {
$scope.title = chapter.titles[0];
}
$scope.onTitleChange = function(b, t) {
// alert(t);
b.selectedTitle = t;
}
});
<head>
<link href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css" rel="stylesheet" type="text/css" />
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.14/angular.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/angular-ui-bootstrap/0.12.0/ui-bootstrap-tpls.min.js"></script>
<meta charset="utf-8">
<title>JS Bin</title>
</head>
<body>
<div ng-app="app">
<div ng-controller="homeCtrl">
<div class="row">
<div class="col-md-4 col-xs-4 col-sm-4">
<select required ng-change="onBookChange(books,book)" ng-model="book" ng-options="bb.bookName for bb in books" class="form-control">
<option value="">--Select--</option>
</select>
</div>
<div class="col-md-4 col-xs-4 col-sm-4">
<select required ng-model="chapter" ng-change="onChapterChange(books,chapter)" ng-options="cha.chapterName for cha in book.chapter" class="form-control">
<option value="">--Select--</option>
</select>
</div>
<div class="col-md-4 col-xs-4 col-sm-4">
<select required ng-model="title" ng-change="onTitleChange(books,title)" ng-options="t for t in chapter.titles" class="form-control">
<option value="">--Select--</option>
</select>
</div>
</div>
</div>
</div>
</body>
you have your ng-models set to book, chapter, title. You just need to assign the default values to these on the scope
$scope.book = $scope.books[0];
//in the onBookChange function
$scope.chapter = book.chapter;
//in the onChapterChange function
$scope.title = cha.titles[0];

Resources