how to stop bind in angularjs - angularjs

I hava a checkbox ,the model status.useJoin also bind the div.
<input type="checkbox" ng-model="status.useJoin" ng-click="toggleJoin($event);" >
<div ng-if="status.useJoin"> show area</div>
when status.useJoin is true ,will show div.
My question is ,when I want to prevent the default action of the checkbox. I will write function toggleJoin like this.
$scope.toggleJoin = function (dimension,$event) {
if (status.useJoin) {
$event.preventDefault();
return;
}
}
the checkbox action is stopped ,but status.useJoin is still modified. How can I stop the bind?

You can use ng-disabled directive
<input type="checkbox" ng-model="status.useJoin" ng-disabled="onYourDisableCondition();" >
$scope. onYourDisableCondition = function () {
if (status.useJoin) { //Add your additional conditions
return true;
}
}

Related

Prevent check of checkbox until function has been called

We are using AngularJS, and we require to run a function that determines whether or not the checkbox the user clicked on is actually checked. I have tried to pass $event on ngChange, but discovered it is unable to pass the $event object. The reason I want to access the $event object is so I could prevent the default behaviour until the required function has been called.
The code is as follows (does not include the code where I attempted to pass $event as it didn't work):
<label for="specificCase">
Yes
<input
type="checkbox"
name="specificCase"
data-ng-click="specificCase.no = false; specificCase.unsure = false;"
data-ng-model="specificCase.yes"
data-ng-change="$ctrl.specificCaseCheck('yes', specificCase.yes)">
</label>
<label for="notSpecificCase">
No
<input
type="checkbox"
name="notSpecificCase"
data-ng-click="specificCase.yes = false; specificCase.unsure = false;"
data-ng-model="specificCase.no"
data-ng-change="$ctrl.specificCaseCheck('no', specificCase.no)">
</label>
controller
function specificCaseCheck(value, boolean) {
//HERE I WANT TO PREVENT THE DEFAULT BEHAVIOUR OF THE CHECKBOX CHECKING
vm.optionSelected = !boolean ? false : true;
vm.caseSpecific = value == 'yes' && boolean ? true : false;
}
Question
How do I keep the checkbox unchecked until I have run a function in the controller?
Since you need to prevent default behavior but dont have the event you can follow the approach of this question Angular 2 Checkbox preventDefault
Basically you need to return false in your event handler to prevent the default behavior of "checking the checkbox when is clicked" then you can click it programatically
For that you can check this question Angular 4 checkbox set programmatically

Trying to validate that at least one checkbox is checked angularJS

Trying to figure out the best way to stay on the same page alerting the user if they have failed to check at least one checkbox.
HTML:
<div class="col3">
<input type="checkbox" ng-model="$parent.value5" ng-true-value="'Togetherness'" ng-false-value="">
<span class="checkboxtext">
Togetherness
</span><br>
<!--<p>We value our people and recognize that <strong>Together</strong> we achieve superior results.</p><br>-->
<div class="col3">
<a ui-sref="form.submit">
<button name="button" ng-click="SaveValue()">Continue</button>
</a>
Back-end angularJS to check if one of the boxes was checked-
$scope.SaveValue = function () {
var valueStatus = [];
if ($scope.value1 === "Methodical")
{
valueStatus.push($scope.value1);
}
if ($scope.value2 === "Relentless")
{
valueStatus.push($scope.value2);
}
if ($scope.value3 === "Togetherness")
{
valueStatus.push($scope.value3)
}
if ($scope.value4 === "Excellent") {
valueStatus.push($scope.value4)
}
if ($scope.value5 === "Ingenious") {
valueStatus.push($scope.value5)
}
return valueStatus
};
Basically I'm wanting to make an array of these values and then return it. However, I want the user to check at least one box. I've tried redirecting back to the page if valueStatus[0] == null. However, I don't think this is the best way to validate and it does not work completely how I think it ought to.
The way I solve this is putting validation on the length of array (valueStatus in your case) with hidden number input. The input will have min validation on. So, if user fails to check at least one, the form is not submitted;
<input type="number" name="valueStatus" ng-model="valueStatus.length" min="1" style="display: none">
Then, you can use normal validation on valueStatus that is available on the form model
myFormName.valueStatus.$valid
This way, most of the logic is put into the template, which is called angularjs way ;)
UPDATE
Forgot to mention:
You need to update the list of checked values on on-change checkbox event
<input type="checkbox" ng-model="checkboxValue1" on-change="updateValueStatus(checkboxValue1)">
<input type="checkbox" ng-model="checkboxValue2" on-change="updateValueStatus(checkboxValue2)">
and in controller
$scope.updateValueStatus = function(value){
var indexOf = $scope.valueStatus.indexOf(value);
if(indexOf < 0) {
$scope.valueStatus.push(value);
} else {
$scope.valueStatus.splice(indexOf, 1);
}
}
Hope it will help people with the same issue
simply just check the valueStatus length is equal to 0 or not
$scope.SaveValue = function () {
var valueStatus = [];
if ($scope.value1 === "Methodical")
{
valueStatus.push($scope.value1);
}
if ($scope.value2 === "Relentless")
{
valueStatus.push($scope.value2);
}
if ($scope.value3 === "Togetherness")
{
valueStatus.push($scope.value3)
}
if ($scope.value4 === "Excellent") {
valueStatus.push($scope.value4)
}
if ($scope.value5 === "Ingenious") {
valueStatus.push($scope.value5)
}
if (valueStatus.length === 0 ) {
console.log('please select atleast one select box')
}
return valueStatus
};
Edited
remove the ui-sref tag and change the state inside your click function
<button name="button" ng-click="SaveValue()">Continue</button>
in the saveValue function add this
if (valueStatus.length === 0 ) {
console.log('please select atleast one select box')
}else{
$state.go('form.submit') // if atleast one selected then the page will change
}

Protractor isSelected giving false reading after re-enabling checkboxes

I have a list of checkboxes and at the top a all checkbox. When toggling the all checkbox, all checkboxes will get deselected or selected.
By default/initially, all checkbox is enabled with all checkboxes checked. So, I will deselect the all checkbox and all the checkboxes will uncheck. This passes no with no issues in protractor:
it('all checkbox is deselected', function() {
modelsAllCheckbox.click();
expect(modelsAllCheckbox.isSelected()).to.eventually.be.false;
});
it('all models should be deselected', function() {
ppvPercentages.modelChoices().then(function(modelChoices) {
modelChoices.forEach(function(modelChoice) {
expect(modelChoice.isSelected()).to.eventually.be.false;
});
});
});
this.modelChoices = function(rowNumber) {
return element.all(by.repeater('model in vehicleCheckboxes.models'));
}
Then I re-enable the all checkbox. I visually can see, in the browser, the all checkbox being checked in all the checkboxes successfully being checked/selected. Hoewever, in the test to assert they are all selected fails:
it('all button is re-enabled', function() {
modelsAllCheckbox.click();
expect(modelsAllCheckbox.isSelected()).to.eventually.be.true;
// give time for all models to set
browser.sleep(3000)
});
it('all models are selected', function() {
ppvPercentages.modelChoices().then(function(modelChoices) {
modelChoices.forEach(function(modelChoice) {
expect(modelChoice.isSelected()).to.eventually.be.true;
});
});
})
<div class="overflow-container">
<!-- all checkbox -->
<input type="checkbox"
ng-model="vehicleAllCheckbox.models"
ng-change="toggleAllModels(vehicleAllCheckbox, vehicleCheckboxes.models, vehicleCheckboxes.year)">All
<div ng-repeat="model in vehicleCheckboxes.models | orderBy: 'description' track by model.description">
<!-- the rest of the checkboxes -->
<input type="checkbox"
ng-change="modelCheckboxToggle()"
ng-model="model.checked" >
{{model.description}}
</div>
</div>
I see all the checkboxes are checked in the browser viusally. Why is modelChoice.isSelected() giving false instead of true up re-enabling the all checkbox?
The problem is in the way you are locating the checkboxes. Currently, you are targeting the parent div elements since you are using the by.repeater() locator:
<div ng-repeat="model in vehicleCheckboxes.models | orderBy: 'description' track by model.description">
Instead, point modelChoices to input elements (your checkboxes):
this.modelChoices = function(rowNumber) {
return element.all(by.repeater('model in vehicleCheckboxes.models')).all(by.model('model.checked'));
}
As a side note, I think you can improve the way you are expecting the checkboxes to be selected, by either using .each():
ppvPercentages.modelChoices().each(function (modelChoice) {
expect(modelChoice.isSelected()).to.eventually.be.true;
});
Or, by using .reduce():
var allSelected = ppvPercentages.modelChoices().reduce(function (acc, modelChoice) {
return modelChoice.isSelected().then(function (isSelected) {
return acc && isSelected;
});
}, true);
expect(allSelected).to.eventually.be.true;
Or, there are other ways as well.

Knockout.js Checkbox checked and click event

We're trying to implement a checkbox and list with the following functionality:
Clicking the checkbox will either clear the array if there are items in there, or add a new item if not.
Remove an item from the array when clicking the Remove button, once the last item is removed the checkbox automatically unchecks itself.
The problem I am having is that if you click to remove each array item, then click the checkbox to add a blank entry, I'm expecting the checkbox to be checked again (as per the checked observable), however it is not?
I have the following code:
http://jsfiddle.net/UBsW5/3/
<div>
<input type="checkbox" data-bind="checked: PreviousSurnames().length > 0, click: $root.PreviousSurnames_Click" />Previous Surname(s)?
</div>
<div data-bind="foreach: PreviousSurnames">
<div>
<input type="text" data-bind="value: $data">
<span data-bind="click: $root.removePreviousSurname">Remove</span>
</div>
</div>
var myViewModelExample = function () {
var self = this;
self.PreviousSurnames = ko.observableArray(['SURNAME1', 'SURNAME2', 'SURNAME3']);
self.removePreviousSurname = function (surname) {
self.PreviousSurnames.remove(surname);
};
self.PreviousSurnames_Click = function () {
if (self.PreviousSurnames().length === 0) {
self.PreviousSurnames.push('');
}
else {
self.PreviousSurnames.removeAll();
}
alet(2)
}
}
ko.applyBindings(new myViewModelExample());
If you are using together the click and the checked then you need to return true from your click handler to allow the browser default click action which is in this case checking the checkbox:
self.PreviousSurnames_Click = function () {
if (self.PreviousSurnames().length === 0) {
self.PreviousSurnames.push('');
}
else {
self.PreviousSurnames.removeAll();
}
return true;
}
Demo JSFiddle.
You need to use a computed to monitor the length of the observable array. This way when the length reaches zero you can react to it automatically.
self.surnames = ko.computed(function() {
var checked = true;
if (self.PreviousSurnames().length === 0) {
self.PreviousSurnames.push('');
checked = false;
}
return checked;
});
Now you will have the blank text box when all of the names are cleared. If you update your binding on the checkbox it will function properly as well.
<input type="checkbox" data-bind="checked: surnames, click: PreviousSurnames_Click" />Previous Surname(s)?
FIDDLE

Check all boxes toggle method not working like expected

I'm wiriting a method to toggle a checklist as checked / unchecked, as follow:
$scope.checkAllToggle = function(dtProvider, destiny, ev) {
$(ev.currentTarget).parent().find('span').html());
data[destiny] = [];
if ($(ev.currentTarget).parent().find('span').html()=='Check all') {
for (var val in data[dtProvider]) data[destiny].push(data[dtProvider][val].id);
$(ev.currentTarget).parent().find('span').html('Uncheck all');
}
else $(ev.currentTarget).parent().find('span').html('Check all');
}
The label of the toggle button changes every time, but the state of the checkboxs only becomes checked after 2 click, from this point change in each 3 clicks.
What's wrong?
Append
if(!$scope.$$phase) $scope.$apply();
to the method make no difference, as prepending $scope to data
Code in plunker: http://plnkr.co/edit/Zf6UzLbC4osRov7IR5Na?p=preview
Rather than do it that way, this would be the easier way to do it.
Make the master input and assign it to a model.
<input type="checkbox" ng-model="master">
Then have your other inputs be tied to the master like this.
<input type="checkbox" ng-model="box1" ng-checked="master">
<input type="checkbox" ng-model="box2" ng-checked="master">
<input type="checkbox" ng-model="box3" ng-checked="master">
Here is your plunker with these changes.
Master Checkbox Plunker
I got your plunker to work by doing this.
$scope.checkToggle = function(dtProvider, destiny, ev) {
$scope.data[destiny] = [];
if ($(ev.currentTarget).parent().find('span').html() == 'Check all') {
for (var val in $scope.data[dtProvider]){
$scope.data[destiny].push($scope.data[dtProvider][val].id);
$(ev.currentTarget).parent().find('span').html('Uncheck all');
}
} else {
$(ev.currentTarget).parent().find('span').html('Check all');
}
$scope.$apply();
};
I could not get it to work if calling safely like if(!$scope.$$phase){$scope.$apply();} but it is working with straight $scope.$apply(). This might have something to do with rootScope and need to be safetly called in a different manner.
See this link: https://coderwall.com/p/ngisma
You also had some missing {} in your code that could have been causing some issues.

Resources