how to do ng-model the right way to choose colors? - angularjs

Use case 1
I choose color from button = preview's color changes
I choose color from color picker works as well the preview changes
If i go to step one again the preview won't changes
it will only happen if i go to color picker then click the button
HTML
<!-- 1. Choose from the buttons listed -->
<div ng-repeat="color in colors">
<button style="background-color: {{ color }}"
ng-click="colorPicked(color)">
</md-button>
</div>
<!-- 2. Choose from the input field -->
<input type="text" name="fname" maxlength="7" ng-model="colorValue">
<!-- 3. Choose from color picker -->
<input id="input-color" value="#f9ad17" type="color" name="color"
ng-model="colorValue" ng-change="colorPicked(colorValue)"/>
<!-- Preview -->
<div style="background-color: {{ colorValue }}; width: 200px; height: 200px">
</div>
ColorController
$scope.colors = [
'#d13438', '#ffb900', '#00cc6a', '#107c10', '#2258af', '#70a3ed',
'#30363d', '#881798'];
$scope.colorPicked = function (color) {
$scope.colorValue = color;
}
}
UI
I have no idea what is the problem

Your error comes from this line:
ERRONEOUS
<input id="input-color" value="#f9ad17" type="color" name="color"
ng-model="colorValue" ng-change="colorPicked(colorValue)"/>
You don't need to set the attributes value and ng-change. The initialisation of the value should be done in the controller:
$scope.colorValue = '#f9ad17';
Since the value is binded you don't need the ng-change.
Here is a complete working fiddle

Change as so:
<input id="input-color" ̶v̶a̶l̶u̶e̶=̶"̶#̶f̶9̶a̶d̶1̶7̶"̶ type="color" name="color"
ng-model="colorValue" ̶n̶g̶-̶c̶h̶a̶n̶g̶e̶=̶"̶c̶o̶l̶o̶r̶P̶i̶c̶k̶e̶d̶(̶c̶o̶l̶o̶r̶V̶a̶l̶u̶e̶)̶"̶ />
$scope.colorValue = '#f9ad17';
The DEMO
angular.module('app', [])
.controller('Ctrl', function ($scope) {
$scope.colorValue = '#f9ad17';
$scope.colors = [
'#d13438', '#ffb900', '#00cc6a', '#107c10', '#2258af', '#70a3ed',
'#30363d', '#881798'
];
$scope.colorPicked = function(color) {
$scope.colorValue = color;
}
})
.color-button {
height: 20px;
width: 20px;
}
<script src="//unpkg.com/angular/angular.js"></script>
<body ng-app="app" ng-controller="Ctrl">
<!-- 1. Choose from the buttons listed -->
<span ng-repeat="color in colors">
<button style="background-color: {{ color }}"
class="color-button"
ng-click="colorPicked(color)">
</button>
</span><br>
<!-- 2. Choose from the input field -->
<input type="text" name="fname" maxlength="7" ng-model="colorValue">
<!-- 3. Choose from color picker -->
<input id="input-color" type="color" name="color" ng-model="colorValue" />
<!-- Preview -->
<div style="background-color: {{ colorValue }}; width: 200px; height: 200px">
</div>
</body>

First of all, don't use style and interpolate values as it may get overwritten. Instead use ng-style directive:
ng-style="{'background-color': colorValue}"
Second, ng-change directive is unnecessery on input-color

Related

Why ng-class is not getting applied to input tag?

Here is my HTML input tag on which I have created conditional ng-class
<input type="text" class="form-control" placeholder="label" name="label"
ng-required="true" ng-class="{ missing: $ctrl.flag=='true'}"
ng-model="$ctrl.DataToSend.label[$ctrl.language]" />
And here is my CSS
.missing {border: solid 1px red;}
When my $ctrl.flag is true ng-class should get applied but it's not happening. Why?
You have to put the class which you want to apply in quotation marks. Otherwise it looks for an AngularJS variable where the string for the class name is contained.
Also make sure your condition is not always false. In your case the $ctrl.flag variable might store a boolean value. So change your condition to: $ctrl.flag
Updated Code:
<input type="text" class="form-control" placeholder="label" name = "label" ng-required="true" ng-class="{ 'missing': $ctrl.flag }" ng-model = "$ctrl.DataToSend.label[$ctrl.language]"/>
You can try this snippet.
Jsfiddle link
Snippet:
var app = angular.module('myApp', []);
app.controller('ctrl', function($scope) {
$scope.flag = true;
$scope.toggleClass = function() {
$scope.flag = !$scope.flag;
};
});
.missing {border: solid 1px red;}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app='myApp'>
<div ng-controller='ctrl'>
{{flag}}
<input type='text' class='form-control' ng-model='test' ng-class="{'missing': flag}" />
<button ng-click='toggleClass()'>
Change
</button>
</div>
</div>
This will work
I found the Issue with my code there is some other CSS which is overriding to my 'missing' css when changed the overridden CSS its started working fine.
input[type="text"].missing {border: 1px solid #ff0000;}
Previously it was
input[type="text"] {border: 1px solid #ddd;}

Handling multiple radio buttons

Here "idDefault" values are not changing. Please help me.
<div class="form-group" >
<label class="control-label">Select Colors : </label>
<div ng-repeat = "color in colorlist">
<input type="radio" name="color" ng-value="true" ng-model="color.idDefault">
{{color.colorName}} </input>
</div>
Colors : {{colorlist}}
and my JSON is
$scope.colorlist = [
{
colorName:'Black',
idDefault:true},
{
colorName:'Red',
idDefault:false} ,
{
colorName:'Bule',
idDefault:false} ,
{
colorName:'Yellow',
idDefault:false} ,
];
Initially black is selected. When selecting other colors, Black isDefault value not changing to false.
First of all as you are using color list for radio buttons , its the way for Checkbox list . But if you wanna use it like this only , you can do it by adding a ng-change in it like -
View Code-
<div class="form-group" >
<label class="control-label">Select Colors : </label>
<div ng-repeat = "color in colorlist">
<input type="radio" name="color" ng-change="changed(color)" ng- value="true" ng-model="color.idDefault"/>
{{color.colorName}}
</div>
Colors : {{colorlist}}
and in controller add a method -
$scope.changed=function(color){
for(var i=0;i<$scope.colorlist.length;i++)
if($scope.colorlist[i].colorName!==color.colorName){
$scope.colorlist[i].idDefault=false;
}
}
Check the fiddle
hope it will work for you.
The method that you are trying to use above is used for checkboxes where you can select multiple value but here you want only one color to be selected at time.
You can this as,
<div class="form-group" >
<label class="control-label">Select Colors : </label>
<div ng-repeat = "color in colorlist">
<input type="radio" name="color" ng-value="color" ng-model="selectedColor">
{{color.colorName}}
</input>
</div>
This way you can get the selected color in your contoller in $scope.selectedColor variable.

Angular - ngClass being added to each clicked radio button (instead of ONLY clicked one)

In my angular app I'm using ng-repeat to generate several radio buttons, the ultimate goal is to add a choiceSelected class (ngClass colour styling) to the label of the clicked radio input. I can add the style to the clicked button, BUT that style is added to every other clicked radio button and I end up with 5 coloured labels. Can't understand why.
Here is the HTML code:
<div class="row" ng-repeat="obj in questionObject.choices">
<div class="radio">
<label class="choice" ng-class="{'choiceSelected': isChecked==$index}">
<input type="radio" name="optradio" ng-model="isChecked" ng-value="$index" ng-click="selectAnswer($index,questionObject)">{{obj.body}}</label>
</div>
</div>
<div class="row" ng-repeat="obj in questionObject.choices">
<div class="radio">
<label class="choice" ng-class="{'choiceSelected': isChecked==$index}">
<input type="radio"
name="optradio"
/*********************************************/
ng-model="isChecked"
ng-value="$index"
/*********************************************/
ng-click="selectAnswer($index,questionObject)">{{obj.body}}
</label>
</div>
</div>
Look at the lines inside the comments, clearly tells that your value of the checkbox($index) is binding to the isChecked variable.
By your, condition in ng-class isChecked==$index it is same for all the elements and so the class is applied for all radio buttons.
if you can update the Json of questionObject , can give you alternative option.
Assuming that questionObject contains the following json
[{
"body": "abc"
}, {
"body": "def"
}, {
"body": "aghi"
} ]
You can use the below code to make your result achieve
<div class="row" ng-repeat="obj in questionObject track by $index" >
<div class="radio" >
<label class="choice"
ng-class="{'choiceSelected': isChecked==$index}">
<input type="radio"
name="optradio"
ng-value="obj.body"
ng-click="selectAnswer($index,obj)">
{{obj.body}}
</label>
</div>
The method selectAnswer should make your work simple. Use this
$scope.selectAnswer=function(number,obj)
{
$scope.isChecked=number;
}
LIVE DEMO
NOTE: In your code the selectAnswer method call in HTML passes the
questionObject fully
Update 1
Reason for manually defining isChecked
Angular looks for the the value of isChecked in the scope because you have used ng-class in the

angularjs form hide unhide triggers validation

I've an angularjs form with validations set. I want to unhide it on click of show button and hide it on click of hide button.
If I play with the input fields and hide and then again unhide, I still see the validation messages which I don't want. Please help me in solving this issue.
Code is as below:
Index.html
<!-- index.html -->
<!DOCTYPE html>
<html>
<head>
<!-- CSS ===================== -->
<!-- load bootstrap -->
<link rel="stylesheet" href="http://netdna.bootstrapcdn.com/bootstrap/3.0.3/css/bootstrap.min.css">
<style>
body { padding-top:30px; }
</style>
<!-- JS ===================== -->
<!-- load angular -->
<script src="http://code.angularjs.org/1.2.6/angular.js"></script>
<script src="script.js"></script>
</head>
<!-- apply angular app and controller to our body -->
<body ng-app="validationApp" ng-controller="mainController">
<div class="container">
<div class="col-sm-8 col-sm-offset-2">
<!-- PAGE HEADER -->
<div class="page-header"><h1>AngularJS Form Validation</h1></div>
<!-- FORM -->
<!-- pass in the variable if our form is valid or invalid -->
<button type="button" ng-click="unhide()" class="btn btn-primary">Show</button>
<form ng-show="showForm" name="userForm" ng-submit="submitForm(userForm.$valid)" novalidate> <!-- novalidate prevents HTML5 validation since we will be validating ourselves -->
<!-- NAME -->
<div class="form-group">
<label>Name</label>
<input type="text" name="name" class="form-control" ng-model="name" required>
<p ng-show="userForm.name.$invalid && !userForm.name.$pristine" class="help-block">You name is required.</p>
</div>
<!-- USERNAME -->
<div class="form-group">
<label>Username</label>
<input type="text" name="username" class="form-control" ng-model="user.username" ng-minlength="3" ng-maxlength="8">
<p ng-show="userForm.username.$error.minlength" class="help-block">Username is too short.</p>
<p ng-show="userForm.username.$error.maxlength" class="help-block">Username is too long.</p>
</div>
<!-- EMAIL -->
<div class="form-group">
<label>Email</label>
<input type="email" name="email" class="form-control" ng-model="email">
<p ng-show="userForm.email.$invalid && !userForm.email.$pristine" class="help-block">Enter a valid email.</p>
</div>
<!-- SUBMIT BUTTON -->
<button type="submit" class="btn btn-primary">Submit</button>
<button type="button" ng-click="hide()" class="btn btn-primary">Hide</button>
</form>
</div><!-- col-sm-8 -->
</div><!-- /container -->
</body>
</html>
script.js:
// app.js
// create angular app
var validationApp = angular.module('validationApp', []);
// create angular controller
validationApp.controller('mainController', function($scope) {
// function to submit the form after all validation has occurred
$scope.submitForm = function(isValid) {
alert(isValid);
// check to make sure the form is completely valid
if (isValid) {
alert('our form is amazing');
}
};
$scope.hide = function(){
$scope.showForm = false;
}
$scope.unhide = function(){
$scope.showForm = true;
$scope.userForm.$setUntouched();
}
});
Below is the plunker link:
http://plnkr.co/49k8P0
To achieving the behaviour what expect, you need to do several changes in your code.
All the form field should belong to one object, like create one object which would $scope.user = {} and then place all user related fields inside your user object like user.username, user.name and user.email so that while clearing form you could directly do user = {}
While hiding for you need to clear a form object, Here the form object would be the name of the form which userForm.
OR
More simpler solution would be use ng-if instead of ng-show. Which will add and remove DOM on basis of showForm value.
Demo Here
If you still want to keep the previously entered data in the fields but only clear the messages then add a variable to scope that is set to true when the form is submitted. The validation messages are only shown when the variable is true. You can then set it to false when you hide. This means that when the form is shown again the messages are hidden.
$scope.hide = function(){
$scope.showForm = false;
$scope.submitted = false;
}
Plunker: http://plnkr.co/edit/dnBu0mD9RLvLdVJJKBGe

angularjs clear backing field when input box hides

I have a page that will hide/show additional elements when an option is selected:
<div ng-app>
<div ng-controller="ctrl">
opt: <select ng-model="model.opt" ng-options="item.id as item.text for item in model.opts"></select>
<br/> <span ng-show="model.opt > 1">
alt: <input type="checkbox" ng-model="model.alt" />
</span>
<div> <pre>{{ model | json }}</pre>
</div>
</div>
</div>
http://jsfiddle.net/v7wsdj74/
How would I setup to get notification when the "ng-hide" is evaluated so that the model fields being hidden can be set back to some default values (in this case null)?
Thanks
Perhaps something like this?
scope.$watch('myParameter', (value) => {
// if myParameter is false set it to null?
}
What you can do, is reset the model on changes:
<select ng-model="..." ng-options="..." ng-change="model.alt = null"></select>
https://jsfiddle.net/bfrola/wzpha8c3/
You can also define a more complex reset function and use ng-change="reset()". Hope this helps.

Resources