ng-click function evaluating on second click (or, unclick) - angularjs

--- HTML ---
<div class="btn-group menuSection">
<div class="menuGrid" ng-repeat="main in mains">
<button type="button" class="btn btn-default btn-sm btn-block"
ng-value="main" btn-radio="main" ng-model="$parent.selectedMain"
ng-click="setDish();"/>
{{main}}
</div>
<div class="menuGrid">
<input type="text" class="form-control input-sm"
ng-model="mainOtherText" ng-show="selectedMain == 'Other'"
placeholder="enter other here"/>
</div>
test : {{mainDish}}
</div>
--- JS ---
$scope.setDish = function(){
if ($scope.selectedMain == 'Other') {
$scope.mainDish = $scope.mainOtherText;
}
else {
$scope.mainDish = $scope.selectedMain;
}
};
I have a grid of radio buttons for selecting menu items, the last of which is 'Other'. When 'Other' is selected, a textbox shows up where the user inputs another item. My goal with the ng-click function is to update the variable mainDish with the value in the other textbox when 'Other' is selected.
This code works, however, the problem arises in that the variable mainDish only updates when the radio button is unselected.
Example - when a button is first clicked, it will have no affect on the variable mainDish, but then when another button is clicked mainDish is updated to the value of the first button clicked.
Any ideas on to why this is happening or ways I could fix it?
EDIT:
As per comment, I'll explain my code a bit more. I have a menu, a list of meals that the user picks from. This list is populated by the ng-repeat command grabbing from an array of meals and creating a radio button for each. The last item in the array is an item called 'Other'. When 'Other' is selected, a textbox appears so the user can input their own dish.
What I want: I want the variable mainDish to be assigned the value of the 'Other' textbox when the 'Other' radio box is selected. For all of the other items, the value of mainDish is just the value of the radio button, but this is not the case with 'Other'.
What I have: It works! But in an odd way. The variable mainDish is only updated when the radio button is deselected. Every time you click a new radio button, the variable mainDish gets assigned the value of the previous button. This is the problem I need help solving.

The problem is that ng-click fires before the ng-model code that updates the scope. If you change it to use ng-change, that will fix it. You also need to add ng-change to your text box to update the scope as the user types.
<div class="btn-group menuSection">
<div class="menuGrid" ng-repeat="main in mains">
<input type="radio" name="dishes"
class="btn btn-default btn-sm btn-block"
ng-value="main"
ng-model="$parent.selectedMain"
ng-change="setDish();"/>
{{main}}
</div>
<div class="menuGrid">
<input type="text" class="form-control input-sm"
ng-model="mainOtherText"
ng-show="selectedMain == 'Other'"
ng-change="setDish();"
placeholder="enter other here"/>
</div>
test : {{mainDish}}
</div>
Here is a working example: http://jsfiddle.net/bnzwx94b/2/

Related

AngularJS possible to click all radio buttons

I create a list of radio button selections, but the problem is that when clicked, they both remain selected, thus not working as a radio button group at all.
I have the same ng-model (a string; 'model') and ng-change for all of them, but the id is different.
<div class="radio-button"
ng-show="vm.forAdmins"
ng-repeat="role in vm.adminRoleDefinitions">
<input id="{{role.name}}" type="radio"
ng-model="role.model"
ng-change="vm.stateChanged(role.name, role.active)" >
{{role.name}}
</div>
Been wrestling with this for a while now, can't see what I've missed.
Radio button will work as a group if you assign name property to those radio buttons. I was also facing this issue then I realized my mistake.
<div class="radio-button" ng-show="vm.forAdmins" ng-repeat="role in vm.adminRoleDefinitions">
<input id="{{role.name}}" type="radio"
ng-model="role.model"
ng-change="vm.stateChanged(role.name, role.active)"
name="roles" >
{{role.name}}
</div>
Try assigning a name attribute to your radio button. name groups the radio button. For example :
<input type="radio" name="someRadio" id="radioOne" />
<input type="radio" name="someRadio" id="radioTwo" />
Now only one is selected at a time.

AngularJS - validation not based on form element

Is there a way to inject some validation - custom or otherwise - that isn't tied to a form element? Like - validate that some condition is met, but have it work with standard AngularJS validation?
Update:
Here's what I'm trying to accomplish:
I have a form contains a list of sections. Each section is controlled by a checkbox, and the section will display (via an ng-if) when the checkbox is checked.
Within each section, there's an opportunity for an item to be selected via a popup modal that is activated by a button click. Until an item is selected for that section, the form needs to be invalid. Once an item is selected for each selection that is checked, then the form needs to be valid.
I have a button at the bottom of the form with an ng-disabled="frm.$invalid". I want that to stay disabled until each section that has been checked contains an item that was selected via the modal.
Update 2:
Here's some example code:
<form class="form-horizontal" role="form" name="frm" novalidate>
<label>Name: </label>
<input type="text" ng-model="name" required/>
<div ng-repeat="orderItem in orderItems">
<input type="checkbox" name="items[]" ng-model="orderItem.selected"/>
<div ng-if="orderItem.selected">
... bunch of form fields
<button ng-click="openExchangeSelectionModal(orderItem)">Select Item</button>
<div ng-show="orderItem.exchange_item">
Selected Item: {{orderItem.exchange_item.name}} - ${{orderItem.exchange_item.price | number: 2}}
</div>
</div>
</div>
<button ng-disabled="frm.$invalid" ng-click="submitOrder">Submit</button>
</form>
Checking if the form is valid won't help you in this case since there is no required input that's not being filled.
What I would recommend is that the disable button would call a function that makes some logic about the number of check boxes expanded and the number of selected items and returns the buttons state (true for active otherwise false)
Let's take the example code you put up:
//some html tags...
<button ng-disabled="checkValid()" ng-click="submitOrder">Submit</button>
</form>
Notice that I changed the frm.$invalid to checkValid function, which is a function that is defined on your controller and can perform any logic you want to determine rather show your submit button or not.

How to disabled a button[update] when there is no changes in a form

<form role="form" id="myForm" name="myForm">
<input class="form-control" ng-model="firstName" type="text" />
<input class="form-control" ng-model="lastName" type="text" />
<button class="btn btn-info" ng-disabled="myForm.$pristine">cancel</button
<button class="btn btn-primary" ng-disabled="myForm.$pristine">update</button
</form>
Assume that there is a list of data in a table.
When I click a data, a modal will pop up with data on it(in the example the firstName and lastName).
Inside the modal there’s an EDIT button that when u click it, two other buttons will appear -- CANCEL and UPDATE. I want to set the update button to disabled while there is no changes yet happening in the FORM.
By using $pristine I found a solution, but there’s one problem:
When I try to edit the data and decide to cancel it (by resetting the current data), the next time I click EDIT the UPDATE button is already enabled even though there are no changes to the data yet.
Is there any solution for this?
On cancel set the form to pristine. This will set $pristine back to true which should disable the buttons.
<button class="btn btn-info" ng-disabled="myForm.$pristine" ng-click="myForm.$setPristine()">cancel</button
For cancel buttons I add a function in the controller to reset all fields and then set the form back to pristine which effectively resets the form.

Ionic ng-click calls same Modal in <input type='button'>

<label class="item item-input">
<span class="input-label" id="depTime">Time</span>
<input type="button" value="{{query.depTime}}" ng-click="openModal(2)" class="button"></input>
<input type="button" value="{{query.depDate}}" ng-click="openModal(1)" class="button"></input>
</label>
openModal function
$scope.openModal = function(index) {
console.log("openModal" + index);
if (index == 1) {
$scope.dateModal.show();
} else {
$scope.timeModal.show();
}
};
http://codepen.io/anon/pen/wGMQJQ
how does the problem cause?
or I should just use /a class='button'/
thanks for replying
This error comes because when you call openModal it always get the value of index=2 it will be better if you use different function for each button then it will work
Short answer:
The problem is that you nest two input controls inside the label.
Just remove or replace label around inputs and everything will start working fine
<body ng-controller="myCtrl">
<span class="input-label" id="depTime">Time</span>
<input type="button" value="{{query.depTime}}" ng-click="openModal(2)" class="button button-outline button-calm"></input>
<input type="button" value="{{query.depDate}}" ng-click="openModal(1)" class="button button-outline button-calm"></input>
See http://codepen.io/ryltsov/pen/aNaxja
Note that i also fixed couple minor bugs (changed modal template dateModal to modal-1 and also updated this modal template to have number 1)
Detailed answer:
http://www.w3.org/TR/html-markup/label.html says:
The label element may contain at most one descendant input element,
button element, select element, or textarea element.
Label elements increase the hit area of the related input. If you have two inputs, when you click on either or on the label text the click is handled by the first input. That's why you always get 2 in the click handler.

How to validate the dynamically created textboxes in angularjs?

I have created textboxes dynamically when button is clicked.But even if the text box is empty it is saving the text boxes.But i have number of text boxes which are created dynamically.how to identify the particular empty text box and validate it.I am trying the validation when save button is clicked.Can anyone help me to solve this.
//onclick creating textboxes
$scope.expndtxt=function(){
$scope.textboxes.push("");
};
//view
<li ng-repeat="textbox in textboxes track by $index">
Label For Inputfield:
<input type="text" id="in_{{$index}}" data-ng-model="$parent.textboxes[$index]"/><button class="btn btn-sm btn-default" ng-click="deletetxtbox($index)">-</button>
</li>
Use angular $valid when the user will click the save button you could use $valid whether it has a value or empty in your controller like
textBoxes.saveButtn = function(textFields) {
if (textFields.$valid) {
<----Put your code ---->
}
else{}
}

Resources