What I'm trying to do is make a number of dynamic radio/checkbox fields based on data that is passed to me. Unfortunately I don't have control over the format of this data but it should be ok to get the job done.
This is as far as I have got: http://plnkr.co/edit/LKwueHUzSrC5JpeBY9So
The format of the data I need to end up with in the end is a simple array like this:
"school_type": [
"Government/State",
"International",
"Co-educational"
]
This data could come from a radio box, or a checkbox if it's selected. Checkboxes are displayed if there is only one option, radios if more than one.
So I can get the fields displaying, but the issues I have are:
The name properties on the radio buttons don't seem to work for
each set.
I can't work out how to get the value of the checkbox/radio selected... back to the controller and into the array I need. I thought the easiest way would be to use the ng-change property available and pass a function to this but I keep getting errors every way I try.
Any help would be appreciated.
There's a couple of problems with your code:
You're not using interpolation where it is needed;
You're not binding the controls to the scope;
Here's your updated code:
<label ng-switch-when="r" class="radio">
<div ng-repeat="option in options">
<input type="radio" name="{{fieldname}}" ng-model="$parent.$parent.selectedid" value="{{option}}">
<span>{{ option }}</span>
</div>
</label>
<label ng-switch-when="c" class="checkbox">
<input type="checkbox" name="{{fieldname}}" ng-false-value="" ng-true-value="{{options[0]}}" ng-model="$parent.selectedid">
<span>{{ options[0] }}</span>
</label>
Note that in order to bind the controls correctly I had to use $parent.$parent for the radio buttons and $parent for the checkbox. That was needed because both ng-switch and ng-repeatcreate new child scopes. So I had to go up one level for the checkbox and two ones for the radio buttons. That could be avoided if you used an object instead of primitives for the bindings. I suggest that you try to refactor your code so it does that. This article has more information on that matter.
And finally, here's a working version of your Plunker.
Related
I am populating dropdowns in a forloop and wish to set the default value for each dropdown based on an expression. This seems to be working but my problem is when I set the default value via ng-selected it also fires change event which is not ideal.
I would like the change event only to be fired if the dropdown is actually changed.
<div layout="row" ng-if="layer.Styles && layer.Styles.length > 1">
<md-input-container class="md-icon-float md-block layer-style">
<md-select ng-change="vm.changeLayerStyle(layer,selectedStyle)" ng-model="selectedStyle" ng-model-options="{trackBy: '$value.Name'}" aria-label="Change Layer Style">
<md-option ng-repeat="style in layer.Styles" ng-value="style" ng-selected="style.IsDefault == true">
{{style.DisplayName}}
</md-option>
</md-select>
</md-input-container>
</div>
Using angular material for the dropdown
Repeating over option elements have a history of giving people problems. Normally i'd tell you to use ng-options on the select instead, but since you specifically need to use some material components, that is not an option.
I know it's not the prettiest solution, but you could solve the problem by keeping a copy of the last value and compare it to the current one, once the change event is fired. If that value has not changed, then ignore the event. This might need some extra tweaking since setting the layer.Styles will probably just trigger a lot of updates.
Since you didn't give us a plunker to play with, i can only suggest you play around with ng-model-options (which you are already using to control track-by) the updateOn property and setting it to something that won't be triggered by you setting the selected property. The value blur comes to mind here.
I have a checkbox that is updated from the model, but then the model is not updated clicking the checkbox.
Within a form I have:
<input type="checkbox" ng-model="acceptEula"> I have read the EULA and I agree
<button type="submit" ng-click="pay()" translate>Proceed to Pay</button>
{{acceptEula}}
Clicking the checkbox, I can see how {{acceptEula}} shows true or false, it works.
When I click the button, I put a breakdown in pay() function. $scope.acceptEula is always false. What could be the problem?
Sorry, the question was not detailed in order to simplify the problem. In reality, I used "ng-switch" in the form.
Finally I have found the problem: "This is a scope inheritance problem due to ng-switch creating it's own scope.". It is well explained at angularjs - ng-switch does not bind ng-model
The solution is to use dot in the model, for example $scope.form.acceptEula
Quick questions. Im generating part of a form dynamically, namely the radio buttons part and I am using an ng-repeat. To do this I have the following code to loop through and list the radio button options:
<div ng-repeat="choice in question.choices">
<input name="{{q.name}}" type="radio" value={{choice.id}} ng-model="choice_[q.answer]" required /> {{choice.choice}}
</div>
I have two issues with this, firstly, im not sure if I am correctly assigning my ng-model dynamically.
Secondly once the model is created it seems to be in its own scope and unusable outside of the repeat due to it being encapsulated within the repeat div.
Is there a way I would be able to access this model? perhaps just passing it through the parent scope using $parent or so?
Any help would be appreciated.
Thanks
I created a plunker to show how to access your model:
Model access demo
<input type="radio" value={{choice.id}} ng-model="$parent.choice" required /> {{choice.choice}}
I used the same model name for every input in the repeat. This way whichever input is selected becomes the active model. That should solve your model naming issue.
Secondly, ng-repeat creates a scope for every template it produces, so you do want to use $parent to access the model on your controllers scope.
I'm working on system where I have an ng-repeat populating from an array of elements, with a radio buttons setting a property. When it loads in, none of the radio buttons are selected, but when I select any of the radio buttons, it binds to the model appropriately. It works in a single format without the outer ng-repeat, so I'm not sure why it refuses to select the radio button from the model.
<div ng-repeat="selectedTag in selectedGroup.tags track by $index" ng-controller="ThemesEdit_TagStylesCtrl">
<div class="type-select">
<label ng-repeat="styleGroup in styleGroups.list" ng-hide="styleGroup.name == 'Settings'">
<input type="radio" name="tagType" ng-model="selectedTag.styleGroupId" ng-value="styleGroup.styleGroupId"/> <span>{{styleGroup.name}}</span>
</label>
</div>
<div ng-include src="another_page"></div>
<div class="clear-float"></div>
<p tag-example="selectedTag" data-style-group="styleGroup"></p>
</div>
I can see that the $parent.selectedTag.styleGroupId comes through on each selectedTag, and it triggers the options in the template that is brought in with ng-include, so I know that is pretty close to working properly. The only remaining issue seems to be that it doesn't automatically select a radio button with a defined ng-model.
I'm fairly new to angular, so it could be something completely obvious, but I was hoping someone could light my way. Thank you for any and all help!
Edit: Updated with two suggestions below. Still no joy, but thought I'd edit the code to the most current iteration.
I would say the solution is ng-value="styleGroup.styleGroupId", documentation here.
I feel pretty dumb - it was something simple that I overlooked. With a single instance, publishing with the name set in <input type="radio" name="tagType" ng-model="selectedTag.styleGroupId" ng-value="styleGroup.styleGroupId"/> <span>{{styleGroup.name}}</span>" worked fine. Once I stuffed it in an ng-repeat, it was publishing under the same name="tagType" and overwriting the selection. Sure enough, when I scrolled to the bottom of my page, the last set of radio buttons were checked appropriately.
Checking the docs, the name is optional, and removing it allowed all the radio button sets to populate properly. I haven't seen any ill effects on anything else - is there anything I should be watching for?
Thanks for the help/thoughts, everyone!
I think you should use ng-model="selectedTag.styleGroupId". selectedTag shouldn't be overwritten by your inner ng-repeat.
UPDATE:
Have a look at this SO answer ng-value needs to be set true.
I noticed that on certain websites, if you want to tick a checkbox on or off, you just need to click the corresponding text. When I put a checkbox with some descriptive text on my page, I have to actually hit the checkbox for it to get ticked. How is the former effect achieved?
Consider using a <label> as in this example:
<input type="checkbox" name="call" id="willcall">
<label for="willcall">click on this text to select the checkbox</label>
This example from: http://www.askdavetaylor.com/make_text_adjacent_to_checkbox_clickable.html
I'm sure that they use a JS script to achieve this. It's most likely a label that is being clicked, and they might add an onclick() event to the label which uses the javascript to find the checkbox and add the CHECKED attribute to it. Sorry for not supplying code, but I hope that gives you some understanding on what those websites do.