MDL not updating two ng-repeats' checkboxes values - angularjs

I'm trying to display two ng-repeats showing the same array in two different formats: A simple list with checkboxes and the same list, with extended info and checkboxes.
The following example works fine in Angular.
<label ng-repeat="item in vm.items">
<input type="checkbox" ng-model="item.selected">
{{item.name}}
</label>
<div ng-repeat="item in vm.items">
<h1>{{item.name}}</h1>
<p>{{item.desc}}</p>
<input type="checkbox" ng-model="item.selected">
</div>
But if I use Material Design Lite, the checked state isn't updated, so when you click in one checkbox, the other one stills the same.
Real example:
<div ng-repeat="item in vm.items">
<div class="mdl-card__title" ng-style="{'background-image': 'url({{item.photo}})'}">
<h2 class="mdl-card__title-text">{{item.name}}</h2>
</div>
<label class="mdl-checkbox mdl-js-checkbox mdl-js-ripple-effect" for="checkbox-{{$id}}">
<input type="checkbox" ng-model="item.selected" ng-change="vm.updateMDL()" class="mdl-checkbox__input" id="checkbox-{{$id}}">
<span class="mdl-checkbox__label">Select {{item.name}}</span>
</label>
</div>
And in the list:
<div ng-repeat="item in vm.items">
<label class="mdl-checkbox mdl-js-checkbox mdl-js-ripple-effect" for="checkbox-list-{{$id}}">
<input type="checkbox" ng-model="item.selected" class="mdl-checkbox__input" id="checkbox-list-{{$id}}">
<span class="mdl-checkbox__label">{{item.name}}</span>
</label>
</div>
If I click one checkbox then the same one in the list, object's selected status gets toggled and the clicked checkbox doesn't change (since it didn't change to selected in the first place)
Anyone else facing this issue? Workarounds?

Related

Angular checklist-model undefined?

<div class="checkbox m-b-15" ng-repeat="list in chkArray.riskForHospitalization" >
<label>
<input type="checkbox" name="M1033" data-checklist-model="pi.risHost" data-checklist-value="list.value">
<i class="input-helper"></i>
{[{list.title}]}
</label>
I want to get the value of the selected checked item but when i submit the data model pi.risHost is undefined
Since your checkbox is inside ng-repeat, all the checkboxes inside the ng-repeat has same model. so use an array of models.
<div class="checkbox m-b-15" ng-repeat="list in chkArray.riskForHospitalization" >
<label>
<input type="checkbox" name="M1033"
data-checklist-model="pi.risHost[$index]"
data-checklist-value="list.value">
<i class="input-helper"></i>
{[{list.title}]}
</label>
Here pi.risHost is an array of model and if you checked the 2nd checkbox. then pi.risHost[1] will be true. and so on

Get ng-repeat data to appear in 4 columns

I'm getting list of data from Db to a view using ng-repeat. In order to select multiple values at once I'm using checklist-model. My code is as follows,
<div ng-repeat="item in items">
<input type=checkbox checklist-model="user.role" checklist-value="item"/>{{item}}
</div>
This will return a long list one below another. What I need is to get these data in the list to be displayed in 4 columns. Any help please!
Working Demo
This is what you are looking for. Hope that solve your problem.
<div ng-repeat="product in products" ng-if="$index % 3 == 0" class="row">
<div class="col-xs-4"> <input type="checkbox" checklist-model="user.role" checklist-value="{{products[$index]}}"/>{{products[$index]}}</div>
<div class="col-xs-4"> <input type="checkbox" checklist-model="user.role" checklist-value="{{products[$index]}}"/>{{products[$index+1]}}</div>
<div class="col-xs-4"> <input type="checkbox" checklist-model="user.role" checklist-value="{{products[$index]}}"/>{{products[$index+2]}}</div>
</div>
Output:
You could use display:inline-block on your elements that you want in a row. How you lay them out within that row could be done different ways depending on what you are seeking.
<div ng-repeat="item in items" style="display:inline-block;">
<input type=checkbox checklist-model="user.role" checklist-value="item"/>{{item}}
</div>

Bind ng-model dynamically with unknown input type

I have a HTML form where I have few questions with different answer type. For example question 1 has answer of type multi check box, question 2 has answer type of radio button, question 3 has answer type of text area.
There can be "n" number of questions with any of the above type.
Using ng-repeat I am able to render the questions on the HTML.
Now the problem is to read the answers filled by user. I need to send the response on submit of the form. I am not able to understand how to bind ng-model to each question.
<form id="SubmitForm" name="SubmitForm" class="form-horizontal" role="form">
<div ng-repeat="question in questions">
<div class="col-sm-10">
<span>{{$index+1}}. {{question.question}}</span>
<div ng-if="question.optionType.id == '1'"><!-- Multiple Choice -->
<div class="checkbox" ng-repeat="option in question.options | split track by $index">
<label><input name="{{question.id}}" type="checkbox" value="" ng-model="answer_question.id">{{option}}</label>
</div>
</div>
<div ng-if="question.optionType.id == '2'"><!-- radio button -->
<div class="radio" ng-repeat="option in question.options | split track by $index">
<label>
<input type="radio" name="{{question.id}}">
{{option}}
<br>
</label>
</div>
</div>
<div ng-if="question.optionType.id == '3'"><!-- text box -->
<textarea rows="5" name="{{question.id}}"></textarea>
</div>
</div>
</div>
<div class="form-group" align="center">
<button id="completeSurvey" name="completeSurvey" class="btn btn-info" ng-click="complete()"><span class="glyphicon glyphicon-ok-sign"></span> Done</button>
</div>
</form>
How do I collect all the data entered by the user and use it in the "complete()" method?
Because of the 2-way binding native to AngularJS, you don't really need to do anything.
As the user updates any of the inputs bound by ng-model to the underlying data model Angular will take care of synchronization.
You can simply call ng-click='complete(questions)' and you'll get the latest & greatest user's input scoped to your complete function.
In your <input> and <textarea> just add ng-model="question.answer". Then you can access the answers through each question's answer property.

Dynamically add UI Bootstrap dropdowns with ng-repeat

I'm new to using AngularJS and UI Bootstrap and I'm trying to add dropdowns dynamically using ng-repeat. The problem is that when any one dropdown is clicked it triggers all of them. I'm guessing I'm doing something really stupid with my code and I would appreciate it if someone could point me in the right direction on how to make this code work:
<div class="form-group" data-ng-repeat="item in ctrl.items">
<div class="col-sm-4">
<input type="text" class="form-control" placeholder="" name="itemDescription" data-ng-model="item.description">
</div>
<div class="col-sm-5">
<div class="input-group">
<input type="tel" class="form-control" placeholder="" name="value" data-ng-model="item.value">
<div class="input-group-btn" dropdown is-open="ctrl.isOpen">
<button type="button" class="btn btn-default dropdown-toggle" dropdown-toggle>Dropdown <span class="caret"></span></button>
<ul class="dropdown-menu dropdown-menu-right" role="menu">
<li></li>
</ul>
</div>
</div>
</div>
The problem is that with more than one dropdown, a click results in all dropdowns being triggered and its probably something really easy but I'm having a hard time with it.
Appreciate any help
/Regards Kris
The issue is is-open="ctrl.isOpen". You are binding the opening of all of them with ctrl. It should be bound to something distinct for each repeat, i.e. something like is-open="item.isOpen"

ng-repeat execution forces input to lose focus

I have an input that is created using ng-repeat
<div data-ng-repeat="(index, answer) in currentQuestion['possible_answers']" class="form-group">
<label class="col-md-3 control-label">Answer {{ index + 1 }}</label>
<div class="col-md-8">
<div class="input-icon">
<i class="fa fa-sun-o"></i>
<input data-ng-model="currentQuestion['possible_answers'][index]" type="text" class="form-control" >
</div>
</div>
</div>
I want this to prepopulate the inputs with the values that are in currentQuestion['possible_answers'] and I also want any changes to bind to this variable as well.
However, everytime I start typing into one of these text fields, I type one letter and then it looses focus of the input box. I have a feeling that this is because I start typing and the data bidning updates currentQuestion. Because currentQuestion is updated, the ng-repeat is executed again.
Is there a way to make the ng-repeat action a one off action isntead of constantly revalutating?
Yes (looking at the symptoms, you did not show us the data) your issue could be because your model is the text in the array that you (may have), so whenever you update the model, it will trigger digest cycle since ng-repeat is tracked by the text. You can easily fix this by providing. track by $index, so that the ng-repeat is watched over and repeat watch gets updated only when the array changes in its length.
<div data-ng-repeat="answer in currentQuestion['possible_answers'] track by $index" class="form-group">
<label class="col-md-3 control-label">Answer {{ $index + 1 }}</label>
<div class="col-md-8">
<div class="input-icon">
<i class="fa fa-sun-o"></i>
<input data-ng-model="currentQuestion['possible_answers'][$index]" type="text" class="form-control" >
</div>
</div>
</div>
Demo
You can also use $index to get the array's index. you do not need to iterate with (key, value).
However i would just make my answer array an array of objects and get rid of all these issues, and it would just be (_note the usage of $index and ng-model):-
<div data-ng-repeat="answer in currentQuestion['possible_answers'] track by $index" class="form-group">
<label class="col-md-3 control-label">Answer {{ $index + 1 }}</label>
<div class="col-md-8">
<div class="input-icon">
<i class="fa fa-sun-o"></i>
<input data-ng-model="answer.text" type="text" class="form-control" >
</div>
</div>
</div>
Demo
The ng-repeat creates a new child scope for each item in the list. In this scope it knows index and answer. You bind the value of the input to something outside the scope, namely the same item in the array. Changing it triggers the list to be redrawn, which causes the input to loose focus.
<div data-ng-repeat="(index, answer) in currentQuestion['possible_answers']" class="form-group">
<label class="col-md-3 control-label">Answer {{ index + 1 }}</label>
<div class="col-md-8">
<div class="input-icon">
<i class="fa fa-sun-o"></i>
<input data-ng-model="answer" type="text" class="form-control" >
</div>
</div>
</div>

Resources