Angularjs three state checkbox with ng-repeat issue - javascript

I'm trying to get a list of questions (retrieved dynamically so we can't hard code them) and then using ng-repeat list them out with a three state checkbox next to each (true, false, null).
The code below works to show the questions with the correct checkboxes, however each time you click on 1 checkbox they all change as they are using the same ng-model (I assume).
How do I get around this?
Thanks
<div class="select-all-checkboxes" flex="100" ng-repeat="(guidCustomerId,item) in items" ng-if="item.type=='Mandatory'">
<span three-state-checkbox ng-model="idv.checkboxModelThree" ng-change="idv.checkBoxonChange()" ng-checked="exists(item, selected_mandatory)"></span>
<h8-red>{{item.question}}</h8-red>{{item.answer}}
<br /><br />
</div>

Can you try?
<div class="select-all-checkboxes" flex="100" ng-repeat="(guidCustomerId,item) in items" ng-if="item.type=='Mandatory'">
<span three-state-checkbox ng-model="item.value" ng-change="item.value = !item.value" ng-checked="exists(item, selected_mandatory)"></span>
<h8-red>{{item.question}}</h8-red>{{item.answer}}
<br /><br />
</div>

Related

Angular: Enable form input for only certain sections of html form

I setting up a form in html to allow users to edit individual profiles if the check box is checks. So far, I'm using a ngFor loop to populate the page with data. The issue is that if I press the checkbox, every item in the returned data becomes editable.
The html looks like this:
<ul class="profiles">
<li *ngFor="let profile of profiles">
<ngb-panel title="Profile ID: {{profile.id}}">
<ng-template ngbPanelContent>
<label>Check here to edit:
<input type="checkbox" [(ngModel)]="checked">
<form>
<fieldset [disabled]="!checked">
<input
type="text"
[(ngModel)]="profile.profileName"
name="profileName"
>
</fieldset>
</form>
</ng-template>
</ngb-panel>
</li>
</ul>
Technically speaking, this does work; once the checkbox is checked, the input below is enabled. The issue here is that, because I'm using an ngFor loop to populate the html with the profile information, checking one checkbox enables ALL the profile sections. What I need to do is set this up so that each profile section will only be enabled if its individual edit checkbox is checked off. Are there any good ways to set this up, while still allowing the for loop?
The checked variable in your example does not appear to be profile-specific (I would need to see your JS code to be 100% sure, but that's what it looks like) so you'll need to make a checked property that corresponds to each profile, either as a property of a profile object, or in some other fashion.
<fieldset [disabled]="!checked"> <-- this is going to be the same for all profiles
<input type="text" [(ngModel)]="profile.profileName" name="profileName">
</fieldset>
In your ts, create a temporary array of Profiles which holds a key for checked for each Profile. That way each profile can be checked/unchecked.
let tempProfiles = profiles.map((elem) => {
let tempElem = {...elem} // don't want to modify the original Objects
tempElem['checked'] = false
return tempElem
})
then loop with tempProfiles in HTML
<ul class="profiles">
<li *ngFor="let profile of tempProfiles">
<ngb-panel title="Profile ID: {{profile.id}}">
<ng-template ngbPanelContent>
<label>Check here to edit:
<input type="checkbox" [(ngModel)]="profile.checked">
<form>
<fieldset [disabled]="!profile.checked">
<input
type="text"
[(ngModel)]="profile.profileName"
name="profileName"
>
</fieldset>
</form>
</ng-template>
</ngb-panel>
</li>

To disable all radio buttons if anyone of them is clicked in angularjs ng-repeat

what i am trying to do here is, i have an ng-repeat in a form and if i click anyone of those input buttons corresponding all buttons get disabled
<div ng-repeat="question in sinSurCtrl.singleSurvey" ng-show="!$first">
<hr>
<p>Q. {{question.questionText}}</p>
<form >
<div ng-repeat=" option in question.questionOptions track by $index">
<label>
<input name="options" type="radio" value="$index" ng-click="sinSurCtrl.questionId=question.questionId; sinSurCtrl.answer=$index+1; sinSurCtrl.createAnswer()" onclick="this.disabled = true">
<span> {{option}} {{$index+1}} {{question.questionId}} </span>
</label>
</div>
</form>
</div>
here is the view-
as you can see if i select anyone of those option it is getting disabled but what i am trying to do is if i attempt anyone option then options corresponding to the same question get disabled.
for example-
in Q3. which is a better orator ?
if i choose option (a) then it get selected and after that automatically bot options (a) and (b) get disabled.
Note- please try to keep solution completely in angularjs or if you want use affordable amount of javascript other then that please avoid using external libraries like jQuery(i know nobody in his senses will handle trouble of using jQuery and angular together but for the sake of example i have included its name)
Proposed solution with some suggested refactoring...
First change the ng-click directive to point to a new onOptionButtonClicked function on sinSurCtrl which takes in the two parameters question and index (which it needs to carry out it's work):
<div ng-repeat="question in sinSurCtrl.singleSurvey" ng-show="!$first">
<hr>
<p>Q. {{question.questionText}}</p>
<form>
<div ng-repeat="option in question.questionOptions track by $index">
<label>
<input
name="options"
type="radio"
value="$index"
ng-click="onOptionButtonClicked(question, $index)"
ng-disabled="question.disabled">
<span> {{option}} {{$index+1}} {{question.questionId}} </span>
</label>
</div>
</form>
</div>
Also take note of the newly added ng-disabled="question.disabled" directive. This is part of the mechanism that will enable/disable the question's controls.
Now move the variable assignments to the new onOptionButtonClicked function. The controller is generally a better place (than the view) for variable assignments, especially if there are several of them on the same directive.
sinSurCtrl.onOptionButtonClicked = onOptionButtonClicked;
function onOptionButtonClicked(question, index){
sinSurCtrl.questionId=question.questionId;
sinSurCtrl.answer=index;
sinSurCtrl.createAnswer();
question.disabled = true; // <--- This is what disables the option buttons
}
This is where an answered question object gets it's disabled property set to true. This in combination with the ng-disabled directive mentioned previously is what disables the option buttons.
On your controller, create a function that checks if a given questionId has been answered and return truthy if it has. Call that function in ng-disabled in the input tag:
<input type="radio" ng-disabled="sinSurCtrl.questionHasAnswer(question.questionId)" ... />

ng-checked event for checkbox in AngularJS

I am trying to use ng-checked for checkbox under ng-repeat.
<div class="listing" ng-repeat="item in list>
<input type="checkbox" class="favor" ng-checked='::isFavorite(item)' ng-click='setFavorite(item)'/>
</div>
There is one method, which I am calling on ng-checked event. But, if there are 50 checkboxes in the list (i.e. 50 items in ng-repeat), then each time the page is drawn, the same method gets called twice an item. Any help would be really appreciable.!!
It would be good if you declare JSON object in the controller for each item.
JS
list=[{name:'Item1',checked:true},{name:'Item2',checked:false}];
HTML
<div class="listing" ng-repeat="item in list>
<input type="checkbox" class="favor" ng-checked='item.checked' ng-click='setFavorite(item)'/> {{item.name}}
</div>

How to refetch a scope value in view using angularjs

First of all sorry if my title doesn't quite explain my problem. I have a form which is create a set of question dynamically. In the code below I use ng-repeat="opt in q.options" and I have a button which add a new option.
My view code
<div>
<label for="">Options: </label>
<a ng-click="addOption($event, $index)">
<i class="icon-plus-sign icon-large"></i> Add option
</a><br /><br />
<div ng-repeat="opt in q.options">
<label><span>{{opt.id}}.</span></label>
<input type="text" ng-model="opt.text" placeholder="Add new possible answer here.">
<a ng-click="q.options.splice($index,1)"><i class="icon-remove-sign icon-large"></i></a>
</div>
</div>
<div>
<label for="required_credit">Answer: </label>
<select id="city" ng-options="c for c in options">
</select>
<!-- <ul>
<li ng-repeat="opt in q.options">{{opt.id}}</li>
</ul> -->
What I want is to reuse q.options in my select tags but it the problem is it doesn't populate. I've used ul li tags then ng-repeat="q.options" and it worked but I want to use it using the select tags.
PS: The reason why I want to use the same model is to simply get the appended data which I inserted dynamically.
For instance:
I have 2 input buttons and I add a new input button
Since I'm using the same model my select option would then be updated then it would have 3 options as well.
Accordingly the ngSelect documentation, ng-model is a required parameter for ngSelect. I believe, you want to store your selected value somewhere ;)

check html checkbox using a button

I'm struggling to find a solution for this anywhere on Google, maybe i'm searching incorrectly but thought I would come and ask the ever trustworthy members of StackOverflow.
I'm wanting to use an html button to check an html check box. There reason I don't want to use the check box will be purely for accessibility reasons because the application i'm developing will be on a terminal and used as via a touch-screen so an HTML check box is too small.
The only issue is that the list of check box's is dynamic as it is populated using an SQL query. Obviously however I can do the same for creating HTML buttons.
Im guessing it will require JavaScript (which I'm perfectly happy using now as I'm finding a lot of the functionality I need in this application needs JavaScript) to do this functionality.
So to clarify: I want to click on a button, say it has a value of "Fin Rot" and that checks the check box with the value "Fin Rot". And then if I clicked another button, say it has a value of "Ich" then it also checks the check box with the value "Ich"
While you can use a button and JavaScript for this, might I suggest a much simpler approach? Just use a <label> that's designed just for this, and style it like a button, for example:
<input type="checkbox" id="finRot" name="something" value="Fin Rot">
<label for="finRot">Some text here, could be "Fin Rot"</label>
or (if you don't want to use id on checkbox and for on label):
<label>
<input type="checkbox" name="something" value="Fin Rot">
Some text here, could be "Fin Rot"
</label>
....then with CSS you can hide the checkbox if needed, but either are clickable to toggle the checkbox.
You can test out a demo here, also showing some button-ish CSS on the label if needed.
This example uses a button to toggle the checkbox on/off.
http://jsfiddle.net/DnEL3/
<input type="checkbox" id="finRot" name="something" value="Fin Rot">
<button onclick="document.getElementById('finRot').checked=!document.getElementById('finRot').checked;">Fin Rot</button>
How about a HTML solution.
<p><input type="checkbox"
value="Another check box"
name="cboxwithlabel" id="idbox"><label
for="idbox">Another
checkbox</label></p>
<label> Creates label for the checkbox or radio buttons.
If you are looking for bootstrap solution, I just created this:
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" />
<div class="container">
<div class="row">
<div class="col-md-6">
<!-- Here starts the component -->
<label class="input-group">
<span class="input-group-addon">
<input type="checkbox">
</span>
<span class="form-control btn btn-primary">
Click to toggle checkbox
</span>
</label>
<!-- Here ends the component -->
</div>
</div>
</div>

Categories

Resources