Angular js not firing change event on an already checked checkbox - javascript

Please check out this fiddle here. I am getting this weird behaviour from angular on change event on an initially checked chekbox. I checked this using jquery as well. The jquery event fires properly whilst the angular event fires only when the checked is initially unchecked.
Here is my complete code btw:
<html ng-app="testing">
<head>
<title>Angular ng-change test</title>
</head>
<body>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js"></script>
<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
<div class="row" ng-controller="ChgCtrl">
<div class="col-md-12">
<form>
<div class="form-group">
<span class="text-info">ng-change</span>
<input type="checkbox" ng-model="formElem.checkbox" ng-change="toggleChange(formElem.checkbox)" ng-checked="formElem.checkbox == 1"/>
</div>
</form>
</div>
<div class="col-md-12">
<div class="col-md-6">
<h3>JQuery change event:</h3>
<P id="jq-messages"></p>
</div>
<div class="col-md-6">
<h3>Angular change event:</h3>
<p>{{message_change}}</p>
</div>
<p class="text-danger">Please note the first click on checkbox.</p>
</div>
</div>
<script type="text/javascript">
var app = angular.module('testing', []);
app.controller('ChgCtrl', function ($scope) {
$scope.formElem = {
checkbox: 1
};
$scope.message_change = '';
$scope.toggleChange = function (data) {
$scope.message_change = data === true ? 'Checked' : 'Unchecked';
console.info(data === true ? 'Checked' : 'Unchecked');
};
});
$(function () {
$('input[type=checkbox]').on('change', function (e) {
$('#jq-messages').html($(this).is(':checked') ? 'Checked' : 'Unchecked');
console.log($(this).is(':checked'));
});
});
</script>
</body>

You can do this with pure angular - jQuery is not needed.
Remove your ng-change and ng-checked attributes and just use ng-model:
<input type="checkbox" ng-model="formElem.checkbox"/>
Then toggle your text with ng-show and the model:
<p ng-show="formElem.checkbox">checked!</p>
<p ng-show="!formElem.checkbox">not checked.</p>
Demo

Removed ng-checked attribute, changed type of $scope.formElem.checkbox, corrected if statement ($scope.formElem.checkbox ? 'Checked' : 'Unchecked')
var app = angular.module('testing', []);
app.controller('ChgCtrl', function ($scope) {
$scope.formElem = {
checkbox: true
};
$scope.message_change = '';
$scope.toggleChange = function (data) {
$scope.message_change = ($scope.formElem.checkbox ? 'Checked' : 'Unchecked');
console.info(data === true ? 'Checked' : 'Unchecked');
};
});
$(function () {
$('input[type=checkbox]').on('change', function (e) {
$('#jq-messages').html($(this).is(':checked') ? 'Checked' : 'Unchecked');
console.log($(this).is(':checked'));
});
});
<body ng-app="testing">
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js"></script>
<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
<div class="row" ng-controller="ChgCtrl">
<div class="col-md-12">
<form>
<div class="form-group">
<span class="text-info">ng-change</span>
<input type="checkbox" ng-model="formElem.checkbox" ng-change="toggleChange(formElem.checkbox)" />
</div>
</form>
</div>
<div class="col-md-12">
<div class="col-md-6">
<h3>JQuery change event:</h3>
<P id="jq-messages"></p>
</div>
<div class="col-md-6">
<h3>Angular change event:</h3>
<p>{{message_change}}</p>
</div>
<p class="text-danger">Please note the first click on checkbox.</p>
</div>
</div>
</body>
ng-change event handler, as the name implies, will fire on target value change, but you are just initializing values, not changing them

My suggestion is not to use Jquery and do it with all angularJS. Also in controller if you want to see change , use $scope.$watch.
Her is demo .

Related

Adding HTML-code for every click with ng-click

I am struggling to understand how to implement an add-function that adds a bit of HTML-code each time I click on a plus-button. The user should be able to add how many questions he/she wants, which means each time you click the button, the new code should be added underneath the previous one. Also I want the input to be added to an array in vm.createdset.question. This is the code I want to add each time I click on a button:
<div class="form-group row question-margin">
<label for="description" class="col-md-2 col-form-label">Fråga 1</label>
<div class="col-md-10">
<textarea type="text" class="form-control" placeholder="Beskriv scenariot och frågan" name="createdset" id="createdset" ng-model="vm.createdset.question.text"></textarea>
</div>
</div>
The button-code:
<i class="fa fa-plus-circle fa-3x new" aria-hidden="true"></i>
You can do this using ng-repeat and an array. All HTML within the div containing the ng-repeat will be repeated for every item in your array.
If you want to keep track of the number of the question you could add newQuestion.id = questionList.length to $scope.addQuestion and instead of using {{$index + 1}} you'll use {{question.id}} instead.
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope) {
$scope.questionList = [];
$scope.addQuestion = function() {
var newQuestion = {};
newQuestion.content = "";
$scope.questionList.push(newQuestion);
}
});
<!DOCTYPE html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.min.js"></script>
</head>
<body>
<div ng-app="myApp" ng-controller="myCtrl">
<button ng-click="addQuestion()">Add Question</button>
<hr />
<div ng-repeat="question in questionList track by $index">
<div class="form-group row question-margin">
<label for="description" class="col-md-2 col-form-label">Fråga {{$index + 1}}</label>
<div class="col-md-10">
<textarea type="text" class="form-control" placeholder="Beskriv scenariot och frågan" name="createdset" id="createdset" ng-model="question.content"></textarea>
</div>
</div>
<hr />
</div>
</div>
</body>
</html>
According to your comments, this should be what you're looking for in your particular case:
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope, adminService) {
var vm = this;
vm.questionList = [];
vm.addQuestion = function() {
var newQuestion = {};
newQuestion.content = "";
vm.questionList.push(newQuestion);
};
vm.save = function() {
adminService.create(vm.questionList);
};
});
app.service('adminService', function() {
var create = function(answers) {
//Handle your answers and send the result to your webserver.
console.log(answers);
}
return {
create: create
}
});
<!DOCTYPE html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.min.js"></script>
</head>
<body>
<div ng-app="myApp" ng-controller="myCtrl as controller">
<button ng-click="controller.addQuestion()">Add Question</button>
<hr />
<div ng-repeat="question in controller.questionList track by $index">
<div class="form-group row question-margin">
<label for="description" class="col-md-2 col-form-label">Fråga {{$index + 1}}</label>
<div class="col-md-10">
<textarea type="text" class="form-control" placeholder="Beskriv scenariot och frågan" name="createdset" id="createdset" ng-model="question.content"></textarea>
</div>
</div>
<hr />
</div>
<div>
<button ng-click="controller.save()">Save</button>
</div>
</div>
</body>
</html>

How to reset input field and checkbox in angularjs

I have a form with single input and another two checkbox labeled with Yes and No.
I want to save the input value when i click yes [this is not the problem].
After clicking yes, input and checkbox should reset. How can i do that?
setting ng-model to null is not working for me.
var app = angular.module("app", ['ionic']);
app.controller("MainCtrl", function ($scope,$timeout,$state) {
$scope.selected='other';
$scope.refresh = function(selected,answer){
if(selected == 'yes'){
$timeout(function(){
$scope.$apply(function(){
$scope.uncheck = false;
})
},250);
}
}
});
<html>
<head>
<link rel="stylesheet" href="http://code.ionicframework.com/1.3.2/css/ionic.css" />
<script src="http://code.ionicframework.com/1.3.2/js/ionic.bundle.min.js"></script>
</head>
<body>
<div class="bar bar-header bar-assertive">
<h1 class="title">Example</h1>
</div>
<div ng-app="app" style="margin-top:64px;padding:20px;">
<div ng-controller="MainCtrl" class="has-header">
<label class="item item-input">
<textarea msd-elastic ng-model="answer.three" placeholder="Your answer"></textarea>
</label>
<div>
<ion-checkbox class="cs-checkbox" ng-model="selected" ng-true-value="'no'" ng-change="statethree(selected,answer)">No</ion-checkbox>
<ion-checkbox class="cs-checkbox" ng-disabled="!answer.three" ng-checked="uncheck" ng-model="selected" ng-true-value="'yes'" ng-change="refresh(selected,answer)">Yes</ion-checkbox>
</div>
</div>
</div>
</body>
</html>
Below is working code with checkboxes but generally in such case it'd be better to use radio buttons (but it would chnage your UI design)
var app = angular.module("app", ['ionic']);
app.controller("MainCtrl", function ($scope,$timeout,$state) {
$scope.selected='other';
$scope.refresh = function(selected,answer){
if($scope.selected){
$timeout(function() {
$scope.answer.three = '';
$scope.selected = '';
}, 250)
};
}
});
<html>
<head>
<link rel="stylesheet" href="http://code.ionicframework.com/1.3.2/css/ionic.css" />
<script src="http://code.ionicframework.com/1.3.2/js/ionic.bundle.min.js"></script>
</head>
<body>
<div class="bar bar-header bar-assertive">
<h1 class="title">Example</h1>
</div>
<div ng-app="app" style="margin-top:64px;padding:20px;">
<div ng-controller="MainCtrl" class="has-header">
<label class="item item-input">
<textarea msd-elastic ng-model="answer.three" placeholder="Your answer"></textarea>
</label>
<div>
<ion-checkbox class="cs-checkbox" ng-true-value="false" ng-model="selected">No</ion-checkbox>
<ion-checkbox class="cs-checkbox" ng-disabled="!answer.three" ng-model="selected" ng-change="refresh(selected,answer)">Yes</ion-checkbox>
</div>
</div>
</div>
</body>
</html>
Also please note that you shouldn't use $apply inside $timeout callback because $timeout already triggers angular digest cycle.

creating textbox element dynamically and bind different model

I am working in angular js application, where i need to create textbox with buttons dynamically that means
<div class="col-sm-4 type7" style="font-size:14px;">
<div style="margin-bottom:5px;">NDC9</div>
<input type="text" name="ndc9" class="form-control txtBoxEdit" ng-model="ndc9">
</div>
<div class="col-sm-4 type7 " style="font-size:14px;">
<div style="padding-top:20px; display:block">
<span class="red" id="delete" ng-class="{'disabled' : 'true'}">Delete</span> <span>Cancel </span> <span id="addRow" style="cursor:pointer" ng-click="ndcCheck(0)">Add </span>
</div>
</div>
this will create below one
i will enter some value in above textbox and click add ,it needs to be created in next line with same set of controls that means (textbox with above 3 buttons need to be created again with the entered value).
Entering 123 in first textbox and click add will create new textbox with delete,cancel,add button with entered value.
Again am adding new value 243 then again it needs to create new textbox down to next line with the entered value (and also the same controls).
finally i want to get all the entered values. how can i achieve this in angular js
You could use ng-repeat with an associative array. Add Would basically push the model value to an array and and also an empty object in the array.
<div ng-repeat ="ndc in NDCarray">
<div class="col-sm-4 type7" style="font-size:14px;">
<div style="margin-bottom:5px;">NDC9</div>
<input type="text" name="ndc9" class="form-control txtBoxEdit" ng-model="ndc.val">
</div>
</div>
<div class="col-sm-4 type7 " style="font-size:14px;">
<div style="padding-top:20px; display:block">
<span class="red" id="delete" ng-class="{'disabled' : 'true'}" ng-click="NDCdelete($index)">Delete</span>
<span>Cancel </span>
<span id="addRow" style="cursor:pointer" ng-click="NDCadd ()">Add </span>
</div>
</div>
</div>
In the controller:
$scope.NDCarray = [{val: ''}];
$scope.NDCadd = function() {
$scope.NDCarray.unshift(
{val: ''}
);
};
$scope.NDCdelete = function(index) {
$scope.NDCarray.splice(index, 1);
};
Plunker: https://plnkr.co/edit/3lklQ6ADn9gArCDYw2Op?p=preview
Hope this helps!!
<html ng-app="exampleApp">
<head>
<title>Directives</title>
<meta charset="utf-8">
<script src="angular.min.js"></script>
<script type="text/javascript">
angular.module('exampleApp', [])
.controller('defaultCtrl', function () {
vm = this;
vm.numbers = [1, 2, 3];
vm.add = function (number) {
vm.numbers.push(number);
}
vm.remove = function (number) {
var index = vm.numbers.indexOf(number);
if(index>-1){
vm.numbers.splice(index, 1);
}
}
});
</script>
</head>
<body ng-controller="defaultCtrl as vm">
<div ng-repeat="num in vm.numbers">
<span>Number : {{num}}</span>
</div>
<div>
<input type="number" ng-model="vm.newNumber">
<button ng-click="vm.add(vm.newNumber)">Add</button>
<button ng-click="vm.remove(vm.newNumber)">Remove</button>
</div>
</body>
</html>

JavaScript - Bootstrap Validator

I am using this plugin: Plugin Link
I am trying to validate, if at least one checkbox out of a checkbox group has been selected. The plugin doesn't support such a functionality. Therefore i googled, and found this, by the plugin author himself: Discussion Link and a working implementation here: Example
I tried implementing it and failed. This is what i have so far:
<div class="col-lg-9">
<?php
// Input form for choosing complaints
foreach (Complaints::getComplaints() as $complaint) {
?>
<div class="form-group">
<div class="checkbox">
<label>
<input type="checkbox" name="complaints[]" data-chkgrp="complaints[]"
data-error="Try selecting at least one...">
<?= Helper::sanitize($complaint->getName()) ?>
</label>
<div class="help-block with-errors"></div>
</div>
</div>
<?php
}
?>
</div>
Plus this is the copied JS Function, that should do the magic...:
<script>
$('[data-toggle="validator"]').validator({
custom: {
chkgrp: function ($el) {
console.log("Some debug output, if it is triggered at all" + $el);
var name = $el.data("chkgrp");
var $checkboxes = $el.closest("form").find('input[name="' + name + '"]');
return $checkboxes.is(":checked");
}
},
errors: {
chkgrp: "Choose atleast one!"
}
}).on("change.bs.validator", "[data-chkgrp]", function (e) {
var $el = $(e.target);
console.log("Does is even work? " + $el);
var name = $el.data("chkgrp");
var $checkboxes = $el.closest("form").find('input[name="' + name + '"]');
$checkboxes.not(":checked").trigger("input");
});
So yeeh. Nothing happens, if i try to run this. None of my debug output is printed in the console. Nothing. The form itself also consists out of some password fields and text fields, the checkbox group - generated in the foreach loop - is just one part of it. The validator works for the text and password fields, but does exactly nothing for the checkbox group. Any ideas?
Thanks! :)
I just tried to make it neat.
please checkout the solution:
Reference: http://1000hz.github.io/bootstrap-validator/
$('#form').validator().on('submit', function (e) {
var validate = false;
$("input[type='checkbox']").each(function(index,e){
if($(e).is(':checked'))
validate = true;
});
if(validate){
//valid
$('.with-errors').html(' ');
} else {
$('.with-errors').html('not valid');
}
//if (e.isDefaultPrevented()) {
// handle the invalid form...
//} else {
// everything looks good!
//}
})
<script src="http://code.jquery.com/jquery-2.1.4.min.js"></script>
<script src="https://netdna.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
<link href="https://netdna.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css" rel="stylesheet"/>
<script src="http://1000hz.github.io/bootstrap-validator/dist/validator.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<form role="form" data-toggle="validator" id="form" action="" method="POST">
<div class="col-lg-9">
<div class="form-group">
<div class="checkbox">
<label>
<input type="checkbox" name="complaints[]" data-chkgrp="complaints[]" data-error="Try selecting at least one...">
Teste1
</label>
<div class="help-block "></div>
</div>
</div>
<div class="form-group">
<div class="checkbox">
<label>
<input type="checkbox" name="complaints[]" data-chkgrp="complaints[]" data-error="Try selecting at least one...">
Teste2
</label>
<div class="help-block with-errors"></div>
</div>
</div>
<div class="form-group">
<div class="checkbox">
<label>
<input type="checkbox" name="complaints[]" data-chkgrp="complaints[]" data-error="Try selecting at least one...">
Teste3
</label>
<div class="help-block with-errors"></div>
</div>
</div>
</div>
<button type="submit" >Validade</button>
</form>

Proper way to check if form is empty in Emberjs

I am using HTML5 validation in my form which is like this,
<script type="text/x-handlebars" id="project">
<div class="row">
<div class="span6">
<div class="well well-small">
<p style="text-align: center">
You can create a new Project by filling this simple form.
</p>
<p style="text-align: center"> Project Name should be minimum 10 characters & There's no limit on
Project Description.
</p>
</div>
<form class="form-horizontal">
<div class="control-group">
<label class="control-label" for="projectname">Project Name: </label>
<div class="controls">
{{!view App.TextFieldEmpty}}
<input type="text" name="projectname" id="projectname" required title="Project Name is Required!" pattern="[A-z ]{10,}" placeholder="Enter Project Name"/>
</div>
</div>
<div class="control-group">
<label class="control-label" for="projectdesc">Project Description:</label>
<div class="controls">
<textarea rows="3" id="projectdesc" name="projectdesc" placeholder="Enter Project Desc"
required="Description Required"></textarea>
</div>
</div>
<div class="control-group">
<div class="controls">
<button class="btn" {{action 'createNew'}}>Add Project</button>
</div>
</div>
</form>
</div>
</div>
</script>
And here's what I have tried to do in App.js,
App.ProjectController = Ember.ArrayController.extend({
actions : {
createNew : function() {
if (!("#project form.form-horizontal") === "") {
App.Project.createNew();
}
}
}
});
App.ProjectRoute = Ember.Route.extend({
});
App.Project.reopenClass({
createNew : function() {
dataString = {
'projectname' : $("#projectname").val(),
'projectdesc' : $("#projectdesc").val()
};
console.log('check');
$.ajax({
type : "POST",
url : "http://ankur.local/users/createNewProject",
data : dataString,
dataType : "json",
success : function(data) {
console.log('success');
}
});
return false;
}
});
As you can see in the actions, I am trying to check if form is not empty then do a Ajax POST. But the problem I am encountering is even if the form is not empty, the button doesn't do anything.
Moreover, if I am including the whole form, it will check checkboxes as well? (I want to have one as well)
What I can do to make sure that user doesn't submit empty form?
This is more of a JS/jQuery question than an Ember one. You should look at the jQuery val() function.
You should validate your form inputs in your view, where you can access the <input elements. Furthermore (!("#project form.form-horizontal") === "") is missing the jQuery selector $.
App.ProjectView = Ember.View.extend({
actions : {
createNew : function() {
if (!(this.$("#projectname").val() === "")) {
App.Project.createNew();
}
}
}
});
There might be some other kinks in your code, it would be helpful if you could put together a jsFiddle - that way it makes it much easier for us to help you and you.
Okay I am going to answer my own question & it seems to be working.
Here's what I did:
App.ProjectController = Ember.ArrayController.extend({
actions : {
createNew : function(event) {
$(":text, :file, :checkbox, select, textarea").each(function() {
if ($(this).val() === "") {
alert("Empty Fields!!");
} else {
App.Project.createNew();
event.preventDefault();
}
});
}
}
});

Categories

Resources