Replace checkbox with images angularjs - angularjs

I have to style/replace all checkboxes and radio buttons with images.
I can do this easily by simply adding a span tag after every input(checkbox / radio) like.
<label for="rememberme">
<input type="checkbox" class="unique" id="rememberme"/>
<span class="icon-checkbox"></span>
</label>
How can i do this in angular js.
I cannot modify all htmls with adding a span element, as if something went wrong it will take time to revert.
But i have a unique class or i can add an attribute to write a directive.
I tried using an attribute but i am unable to inspect span element generated, it is working good if i use it as an element.
If i use as an attribute it is giving an output as
<input type="text" class="form-control" custom-input="">
<input type="text" class="form-control">
<span class="icon-checkbox">Checkbox icon</span>
</input>
is this Valid ?
Plunker here

I wouldn't worry about a custom directive just to replace the checkboxes with images. You could do this with CSS like this:
<!--HTML-->
<input type="text" class="form-control checkboxwithicon">
/*CSS*/
.checkboxwithicon{
position:relative;
}
.checkboxwithicon::after{
content:url('http://icons.iconarchive.com/icons/icojam/blueberry-basic/32/check-icon.png');
position:absolute;
top:-10px;
left:15px;
}
And position the image properly so that the checkbox is hidden.

You can write a directive that does generate the span icon-checkbox after the element (it's supposed to be a checkbox) for you and make it act like an attribute, then you can tag it in every input checkbox that you want. Even something wrong happens and you are not happy with the change, you don't have to waste your time and effort to revert the things back, just modify on the directive only.

I made it working from your suggestions with out any change to HTML for easy fallback
.directive('input',function(){
return{
require: '?ngModel',
restrict:'EAC',
link:function(scope,element,attr){
var html = angular.element("<span class='icon-checkbox'>Checkbox icon</span");
if( (angular.lowercase(element[0].tagName)==="input") && (angular.lowercase(attr.type)=== "checkbox"))
element.after(html)
}
}
})
Working Plunker

Related

Update a span in a ng-repeat using ng-keyup

In a repeater and I display some records with some data, input field and a span tag in each row. When the user enters numeric value into the input field,
I want to do a calculation on it and display the result in the span tag. This will happen on keypress using ng-keyup
I’ve tried this but its not working, probably becuse I'm not using the model correctly...
<div ng-repeat="bet in $ctrl.bets">
<input class="form-control input-sm" ng-model="$index" type="text" ng-keyup="$ctrl.getReturn($index)">
<span>Return: </span><span id="$index" ng-model="$index"></span>
</div>
And in my controller I have this
vm.getReturn = function(index){
document.querySelector('#' + index ).html(value / 2);
}
I know its way off, but can someone tell me how to do this? Ta.
1st thing you can use ng-model only with input, select & special bootstrap components, Not span element. You could use ng-bind do bind value one way.
Other thing is don't play with $index which is added & managed by ng-repeat directive itself. I'd say rather add new property inside bet(each element of bets).
Markup
<div ng-repeat="bet in $ctrl.bets">
<input class="form-control input-sm" ng-model="bet.myValue" type="text" ng-keyup="$ctrl.getReturn(bet.myValue)">
<span>Return: </span><span id="$index" ng-bind="vm.getReturn(bet.myValue)"></span>
</div>
Accordingly manage calculation in getReturn function.
vm.getReturn = function(val) {
return (val > 0 ? (val / 2): 0);
}

ng-readonly not working in angular checkbox

Can I use ng-readonly directive in a checkbox?
The checkbox is writable even after it is decorated with ng-readonly.
Html:
<input type="checkbox" ng-model="model" ng-readonly="test" /> {{model}}
Controller:
myApp.controller('MyCtrl', function($scope) {
$scope.test = true;
});
Added Fiddle
if you want to disable it use this:
<input type="checkbox" ng-disabled="true" ng-model="test" />
If you like to have it "more" visible, you can always use a little javascript trick:
<input type="checkbox" ng-model="model" onclick="return false;" />
ng-readonly only work with input type="text"
see documentation here -https://docs.angularjs.org/api/ng/directive/ngReadonly
The HTML specification does not require browsers to preserve the values of boolean attributes such as readonly. (Their presence means true and their absence means false.) If we put an Angular interpolation expression into such an attribute then the binding information would be lost when the browser removes the attribute. The ngReadonly directive solves this problem for the readonly attribute. This complementary directive is not removed by the browser and so provides a permanent reliable place to store the binding information.
In my case I did this, and it worked for me. I think that way I don't directly access the DOM. If someone see any error, please let me know. Thanks.
HTML
<input type="checkbox" name="name" id="name" [checked]="true" (click)="onNoClick($event)">
TypeScript
onNoClick(event: Event): void {
event.preventDefault();
}
Using CSS:
md-checkbox[ng-readonly="true"]{
z-index: -1;
}
or
md-checkbox[ng-readonly="true"]{
pointer-events: none
}
The last, doesn't work in IE
Also try [attr.disabled];
<input type="checkbox" [attr.disabled]="true"> </input>

angular.element is not working in tabset directive of angular js

I'm using tabset directive of angular js and using twitter bootstrap slider in tab,
My slidestop event is not calling but it's working well outside tab.
I know that tabset directive have its own scope , but dont know solution of following problem:-
<tabset class="tab-container">
<tab heading="tab1">
<div class="form-group">
<label>any Level</label>
<div class="input-group w-md">
<input id="slider" ui-jq="slider" ui-options="{min: 0,max: 10,step: 1,value: {{any_level}}}"
class="slider slider-horizontal form-control" type="text"
ng-model="any_level"> {{any_level}}
</div>
</div>
</tab>
</tabset>
controller code
......
angular.element("#slider").on('slideStop', function(data){
alert('asdasd');
})
problem is - alert is not coming when slider inside tab,alert is comming when slider outside tab
i am using this slider
Thanks
i have solved using ui-event directive to fire slidestop event
Html Code
<input id="slider"
ui-event="{slideStop: 'alertChange($event)'}" ui-jq="slider"
ui-options="{min: 0,max: 10,step: 1,value: {{any_level}}}"
class="slider slider-horizontal form-control" type="text" ng-model="any_level">
{{any_level}}
Controller Code
$scope.alertChange = function(data){
console.log(data.value); // i can get slider value on slidestop
}
Just don't use angular.element in an angular app.
EDIT : This isn't really working with ui-slider. Till ui-slider is work in progress i just woudn't use it.
Add this to your input :
ng-change="alertChange()"
And this to your controller :
$scope.alertChange = function(){
alert('hi');
}
What wasn't working ? In most of the case an angular.element will try to bind your even to the element too early. Your DOM "#slider" element isn't probably loaded when your try to bind.
EDIT An alternative :
First, after paying more attention i wouldn't recommend this slider at all.
This is actually a work in progress and isn't really reliable.
I made you an exemple of a html slider with binding in this plunker
You slider looks like this :
<input id="slider"
ng-model-options="{ debounce: 100 }"
min="0"
max="100"
ng-init="any_level = 0"
ng-change="alertChange()"
type="range"
ng-model="any_level">
This will update the model each time the value will not change for 100miliseconds. You need this to avoid firing too much ng-change function.
In your javascript you just need to declare your function
$scope.alertChange = function(){
console.log("I changed !");
//or anything else you want to do
}
I know this is not a solution but an alternative. It's not sexy as the other slider, but at least it works.
Hope it helped you.
The slider you are using has an example demonstrating how to do this. Take a look at box "12" on this page: http://angular-ui.github.io/ui-slider/demo/demo.html
In your controller you can add the following:
$scope.slider = {
'options': {
stop: function (event, ui) { $log.info('Slider stop'); };
}
And your HTML you must reference slider.options so your callback is fired:
<div ui-slider="slider.options"
min="0" max="50" ng-model="any_level"></div>

AngularJS Form is not in HTML

I am trying to use AngularJS Validation in order to validate a simple form, however I was having troubles getting my ng-class to show the correct class based off whether or not the input was dirty or not. Then when I looked at the actual HTML of the page, the <form> tags are not even in the document at all!
<form novalidate name="infoForm">
<p>To start, provide some basic information about the project.</p>
<ul class="ulFormGeneral">
<li>
<label>Company name</label>
<input id="CompanyName" ng-class="{ cvError : infoForm.CompanyName.$dirty }" ng-model="form.CompanyName" name="CompanyName" maxlength="100" type="text" required />
</li>
</ul>
</form>
I want the cvError class to be added to this input if it is dirty, but nothing happens when I look at this in the browser. What am I doing wrong that is causing the <form> to just leave the DOM and then not work with my Angular expressions?
Welcome to the Angular world, no forms required! Here, the model is king. It looks like the problem is the ng-model and ng-class are point at different places.
Point everything at form.CompanyName (assuming that is the model name is form in the $scope):
<input id="CompanyName" ng-class="{ cvError : form.CompanyName.$dirty }" ng-model="form.CompanyName" name="CompanyName" maxlength="100" type="text" required />
The ng-model binds to the $scope. When you change the input field, it is automatically updated in the $scope. No form is needed or hitting a submit button to get the data. The $scope is updated with each key stroke.
The controller should do the work of figuring out what to do with the changes in the model. For example, you can add an ng-click to a button that fires a function defined by the controller to save the model.

Required field Angularjs 1.2 and Bootstrap 3

With the changes to angularjs and bootstrap 3 I have been unable to create a form field that's required where the item will be surrounded with red highlight by only adding the required parameter to the input field. Here is a plunker with how I have it setup on my system and would expect it to work. I can't seem to find any documentation on bootstraps site about required either so that would really help if anyone can find that.
Plunker
EDIT: Replaced all the following with below comments ideas... I would still like a solution where I don't need to write any css and use Bootstrap 3.
My form field looks like this:
<body ng-app>
<div ng-controller="Controller" class="container">
<form novalidate class="simple-form" name="myForm">
<div class="form-group col-sm-4">
Name: <input type="text" ng-model="name" name="name" class="form-control" required/>
E-mail: <input type="email" ng-model="email" name="email" class="form-control" required/>
<small class="error"
ng-show="myForm.email.$error.required">
Your name is required.
</small>
</div>
</form>
</div>
</body>
Script.js Looks like this:
function Controller($scope) {
$scope.name = "Test";
$scope.email = "";
}
Style.css looks like this:
input.ng-invalid {
border: 1px solid red;
}
While this works it replaces the bootstrap css with the css above. I would much prefer to simply add in required to an element and not have to rewrite the css to add the hue and the animation.
I agree with both of the other two answers but would like to add more
I think your main problem is that Bootstrap 3 removed styling based on the :invalid and related pseudo-classes (see here for why). This is where the red outline in bootstrap 2.x came from.
Firstly, to fix your plunker you should:
Bootstrap your app with ng-app as Mike says
Put your input in a form with novalidate
Give a model to your input with ng-model so that it can be invalidated (by angular, using classes)
Move jQuery script include before bootstrap as it is a requirement of bootstrap.
Now you have a plunker where the correct classes are applied to indicate input validity. You won't yet have styling on these, but they won't depend on your browser's HTML5 form validation, so will work in anything angular supports.
To apply styling, you can either use straight CSS and apply it to the ng-valid, ng-invalid, ng-invalid-required etc classes, or you can use the ng-class suggestion from this comment to apply bootstrap's classes when you need them
ng-class="{'has-error': formname.inputname.$invalid}"
if you have named your input and wrapped it in a control.
Updated plunker: http://plnkr.co/edit/mE3dkG?p=preview
Edit
I had a go at making a directive for this too. It may be overkill, but this should work wherever you have a form-group class and add an ng-form to the same element
.directive('formGroup', function(){
return {
restrict: 'C',
require: '?form',
link: function(scope, element, attrs, formController){
if(!formController)
return;
scope.$watch(function(){
return formController.$valid;
}, function(valid) {
if(valid)
element.removeClass('has-error');
else
element.addClass('has-error');
});
}
};
});
Yet another plunker: http://plnkr.co/edit/UQjRrA?p=preview
* The email will not be valid unless it looks like an email
You have a couple of things missing here. First, in order for a form field to validate it needs a unique name:
<input class="form-control" type="text" name="test" required/>
Second, in order to disable stock HTML5 validation, you need to add a novalidate attribute to the form:
<form class="form-horizontal" name="myForm" role="form" novalidate>
Third, and most importantly, your example has no app or controller associated with it, so angular is completely ignoring it. That one you have to fix yourself.
Read more about angular forms here: http://docs.angularjs.org/guide/forms
I suggest you this excellent step by step : http://www.ng-newsletter.com/posts/validations.html

Resources