I have built a cross platform app using Monaca, Onsen UI and AngularJS.
On a page I have a list of items, each with a sub-list of radio buttons created as below in my view.html
<ul class="list">
<li class="list__item" ng-repeat="checkItemDescription in data">
<span class="list__item__line-height"><strong>{{checkItemDescription.checkitemdesc}}</strong></span>
<label class="radio-button" ng-repeat="option in checkItemDescription.options">
<input type="radio"
name="option_question_{{option.fleetcheckitemid}}"
ng-model="option.fleetcheckid">
<div class="radio-button__checkmark"></div>
{{option.checkvaluedesc}}
</label>
</li>
</ul>
The list is built and displayed as I want and the user can click on and of the radio buttons to select them.
When the user selects any of the radio buttons on any of the items, I need to save both the "checkItemDescription" ID as well as the "option.fleetcheckid" to a JSON object. My list of items can be of any length and I need to send each list item as a JSON object to my Database.
How do I send bot the "checkItemDescription" ID as well as the "option.fleetcheckid" when my ng-model only contains the value of "option.fleetcheckid"
If the purpose is to be used one time, you can use ng-hide and pass the variable $scope.InputSet and then ng-change, on the function called set the $scope.InputSet as true and the logic you need.
<ul class="list" ng-hide="inputSet">
<li class="list__item" ng-repeat="checkItemDescription in data">
<span class="list__item__line-height"><strong>{{checkItemDescription.checkitemdesc}}</strong></span>
<label class="radio-button" ng-repeat="option in checkItemDescription.options">
<input type="radio"
name="option_question_{{option.fleetcheckitemid}}"
ng-model="option.fleetcheckid"
ng-change="funcToCall(checkItemDescription.id, option.fleetcheckitemid)">
<div class="radio-button__checkmark"></div>
{{option.checkvaluedesc}}
</label>
</li>
</ul>
Controller
$scope.funcToCall = function(checkItemDescription.id, option.fleetcheckitemid){
$scope.inputSet = true;
//Your logic...
};
If you want to remove just that checkbox you have to pass the option and delete it
$scope.funcToCall = function(checkItemDescription.id, option){
// no need to use ng-hide here
$scope.optionId = option.id;
//remove the option
delete option;
//Your logic...
};
This should work.
Related
I have list of option and using ngDefaultControl Angular directive but formcontrol value show empty on button click.
I want to bind value to form control on button click without using setValue or patchValue methods.
example:
<h3>input text search dropdown</h3>
<div class="result">
Selected Value:
{{
rootForm.get('category')?.value
? rootForm.get('category')?.value
: 'Please select value'
}}
</div>
<br />
<form [formGroup]="rootForm">
<div class="list-popup">
<ul class="list" [formControlName]="'category'" ngDefaultControl>
<li class="item" *ngFor="let option of listValues" [value]="option">
<button type="button" class="item-option" tabindex="-1">
<span class="item-label">{{ option }}</span>
</button>
</li>
</ul>
</div>
</form>
is it possible to bind value from UI in control for the same on selection? Could you please suggest me workaround.
here is the stackblitz
Thanks in advance.
Angular doesn't know what to do when you put a formControl on a ul. In order to do what you want, you have to create a component (or directive) which implements ControlValueAccessor and move the code related to your form control there.
Implementing ControlValueAccessor means implementing the following three functions: writeValue, registerOnChange, registerOnTouched. In this way, Angular will know what to do with your component.
For example, you can follow this example
So I have a hidden DOM structure that I will make visible when clicking on a button (to add some input fields). Now I also want to remove those input fields if not necessary anymore. This is my structure that I clone with jQuery:
<ul id="CTcontainer" class='hidden removeContainer'>
<li>
<label>Content Type Name:</label>
<input class="json-input" type="text" name="CT_name">
</li>
<li>
<label>Content Type Group:</label>
<input class="json-input" type="text" name="CT_group">
</li>
<li *ngIf="contentTypeArray.length != '0'">
<label>Inherit from Content Type:</label>
<select class="json-input" name="CT_contentTypeInherit">
<option *ngFor="let ct of contentTypeArray">{{ ct.name }}</option>
</select>
</li>
<li>
<button type="button" class="btnSubmit" (click)="removeThisCT($event)">Remove these ContentType input fields</button>
</li>
</ul>
Clicking on the "add" button:
public addNewCT(event: Event) {
$('#ContentTypes').append($('#CTcontainer').clone(true, true).removeAttr('id').removeClass('hidden'));
}
When then clicking on the button it should fire this:
public removeThisCT(event: Event) {
alert('testclick');
console.log('testclick');
// $(this).closest('.removeContainer').remove();
}
But nothing happens, debugging in dev tools also shows I'm not entering the function when clicking the button. It seems like my event isn't cloned with? Looking at jQuery .clone() it said to add (true, true) to clone with dataAndEvents and deep events etc. but seemingly doesn't work?
Is this because it's an angular on click event and not a jquery .on('click',) event?
Angular will compile your whole template into javascript to make it fast loading, easy to compress, able to deliver your app as a single file and so forth. More importantly in your case, adding angular template code on the fly will not work, since you are completely bypassing the angular compiler.
As a rule of thumb; when you're writing jquery to manipulate the DOM, you should really question yourself if this really is what you want, and if there's no Angular way of dong it. For a start, all component included in an ngIf or ngFor will be removed completely from the dom once the ngIf turns false or the ngFor does not contain the same numer of elements no more. Use them, and ditch the jquery.
If you want to include whole sets of logic dynamically, read this specific part of the guide:
https://angular.io/guide/dynamic-component-loader
A little piece of code that might help you:
<ul *ngIf="cts.length > 0">
<ng-template ngFor let-ct [ngForOf]="cts">
<li>
<label>Content Type Name:</label>
<input class="json-input" type="text" name="CT_name">
</li>
<li>
<label>Content Type Group:</label>
<input class="json-input" type="text" name="CT_group">
</li>
<li *ngIf="contentTypeArray.length != '0'">
<label>Inherit from Content Type:</label>
<select class="json-input" name="CT_contentTypeInherit">
<option *ngFor="let ct of contentTypeArray">{{ ct.name }}</option>
</select>
</li>
<li>
<button type="button" class="btnSubmit"
(click)="removeThisCT($event)">Remove these ContentType input fields</button>
</li>
</ng-template>
</ul>
adding a ct (whatever that may mean, don't use abreviations in code)
public addNewCT(event: Event) {
this.cts.push({name: 'new ct'});
}
public removeCT(event: Event) {
this.cts = [...this.cts.filter(ct => ct.name != event.name)];
}
I currently have this UI:
the problem is that when I click one radio button, any preselected button will become unselected. So that's telling me that there aren't different input groups - all of the <input> tags are probably in one big group.
This is probably a pretty vanilla problem, but I am simply not an HTML or Angular expert.
Here is the code for this, there is an outer loop and an inner loop using ng-repeat:
<form name="myQuestionsForm" ng-submit="submit()"> // outer form
<div class="panel panel-default" ng-repeat="q in questions | orderBy:[]">
<h1>{{q.prompt.value}}</h1>
<div class="panel-body">
<form id="aform"> // inner form
<div ng-repeat="c in q.children | orderBy:[]">
<div ng-if="c.kind == 'text'">
<label>
{{c.value}}
<textarea name="response" class="form-control" ng-value="c.value" ng-model="q.newResponse.value"></textarea>
</label>
</div>
<div ng-if="c.kind == 'checkbox'">
<label>
{{c.value}}
<input type="checkbox" name="response" class="form-control" ng-value="c.value" ng-model="q.newResponse.value">
</label>
</div>
<div ng-if="c.kind == 'radio'">
<label>
{{c.value}}
<input type="radio" name="response" class="form-control" ng-value="c.value" ng-model="q.newResponse.value">
</label>
</div>
</div>
</form>
</div>
</div>
<div style="text-align: center;">
<button type="submit" class="btn btn--success btn">
<h5>Submit</h5>
</button>
</div>
</form>
Perhaps the reason this is happening is because I have nested forms? Maybe I need to get rid of the outer form?
Group radio buttons with the name attribute.
<input> type attribute
The type of control to display. The default type is text, if this attribute is not specified. Possible values are:
radio: A radio button. You must use the value attribute to define the value submitted by this item. Use the checked attribute to indicate whether this item is selected by default. Radio buttons that have the same value for the name attribute are in the same "radio button group". Only one radio button in a group can be selected at a time.
– MDN HTML Element Reference - <input>
See also:
AngularJS input[radio] Directive API Reference
AngularJS ng-value Directive API Reference
AngularJS ng-checked Directive API Reference
I'm trying to generate multiple pairs of a number form and a checkbox.
Clicking the checkbox disables the number field, The problem is that only the first pair is working. Can someone help me?
here's my code: addHRGrade.blade.php
#extends('layouts.default')
#section('content')
<!-- opening the form -->
{{ Form::open(array('url' => 'students/create', 'method' => 'PUT')) }}
#foreach($students as $stud)
<ul>
<li>
<!-- Printing the students retrieved from the dataabase -->
{{ $stud->LName. " , " .$stud->FName }}
<!-- Making a text field for every students -->
<div ng-app="" >
<input name="grade" id="no_grade" type="checkbox" value="0" ng-model="checked" />
<label>No Grade</label>
<input name="grade" id="num_grade" type="number" value="65" ng-model="number" ng-disabled="checked"/>
</div>
</li>
</ul>
#endforeach
<!-- Save button -->
<p> {{Form::submit('Save')}} </p>
<!-- Closing the form -->
{{ Form::close() }}
#stop
Main issue
You're declaring one ng-app="" per table row. I don't think that's what you want to do. You should wrap everything into a single app. Also, you don't assign anything to ngApp and also ngController so your not able to implement any further logic.
Side issues
When you fixed the main issue, you'll see, that every checkbox and textbox will display the same value, since you assign the same model to each checkbox resp. textbox.
The value="65" won't do anything. You want to display the models data, so the models data (which is undefined at startup). To set the initial value use ng-init="number=65".
I have an unordered list containing radio inputs and labels. When a user clicks on the list item it toggles some info and selects the radio input.
However, due to the above, if the user clicks onto the actual radio input itself, it does not select it, as I guess the click is registered against the radio and not the list item itself?
Is there any cure?
jQuery('#sdmlist li.item').click(function(e) {
jQuery('#sdmlist li.item address').slideUp();
jQuery("address",this).slideToggle("slow");
jQuery("input[type=radio]", this).attr('checked',true);
var element = jQuery("input[type=radio]", this).val();
...
return false;
});
and some html:
<ul id="sdmlist">
<li class="item"><input type="radio" name="1" id="1">1 <address>test 123</address></li>
<li class="item"><input type="radio" name="2" id="2">2 <address>test 23</address></li>
<li class="item"><input type="radio" name="3" id="3">3 <address>test 3</address></li>
</ul>
That behavior is caused by return false stopping the default behavior of the click event who has been propagated by then click on the radio. The default behavior of the radio is, of course, the radio beign checked.
Just remove the return false and it work : http://jsfiddle.net/4v9R9/2/