form into ngfor and getting data in array - arrays

Problem- Here I'm using a single HTML Form. but in many cases, I'll get multiple counts of rooms and multiple counts of adults according to rooms.so I'm using *ngFor for multiple times of forms according to roomwise adults.
So in case, I have 2 rooms, and in particular rooms, I have 2 adults. so this form will repeat 4 times according to adults.
I have to save the all data in an array. But in FormGroup I'm getting only one form data only even I fill all forms.
this form repeats according to roomdetails.adult
HTML File
<div *ngfor="let item of roomdetails; let i = index" [attr.data-index]="i">
<form [formgroup]="ravelerDetails">
<div class="row">
<mat-card>
<h2 class="titleHeader">ROOM {{i+1}}</h2>
<ng-container formgroupname="customer_detail" *ngfor="let items of item.adult;>
<mat-form-field appearance="outline" color="primary" class="col-md-2">
<mat-label>Salutation</mat-label>
<mat-select [formcontrol]="salutation">
<mat-option value="Mr">Mr.</mat-option>
<mat-option value="Mrs">Mrs.</mat-option>
</mat-select>
</mat-form-field>
<mat-form-field appearance="outline" color="primary" class="col-md-5">
<mat-label>First Name</mat-label>
<input matinput placeholder="First Name" [formcontrol]="first_name" maxlength="25">
<mat-error *ngif="first_name.hasError('required')">
<strong>First Name</strong>is required.
</mat-error>
</mat-form-field>
<mat-form-field appearance="outline" color="primary" class="col-md-5">
<mat-label>Last Name</mat-label>
<input matinput placeholder="Last Name" [formcontrol]="last_name" maxlength="25">
<mat-error *ngif="last_name.hasError('required')">
<strong>Last Name</strong>is required.
</mat-error>
</mat-form-field>
</ng-container>
</mat-card>
</div>
</form>
</div>
TS File
initDos() {
return this.fb.group({
salutation: this.salutation,
first_name: this.first_name,
last_name: this.last_name,
})
}
travellDetiles() {
this.ravelerDetails = this.fb.group({
customer_detail: this.fb.array([this.initDos()]),
checkin_date: this.hotelSearch.checkin_date,
checkout_date: this.hotelSearch.checkout_date,
no_adult: this.hotelSearch.no_adult,
no_children: this.hotelSearch.no_children,
no_room: this.hotelSearch.no_room,
});
}
get dosArray() {
return this.ravelerDetails.get('customer_detail') as FormArray;
}
dos() {
this.dosArray.push(this.initDos());
}
removeDos(index) {
this.dosArray.removeAt(index);
}
Output
{
"no_room": "1",
"checkin_date": "2022-11-5",
"checkout_date": "2022-11-6",
"no_adult": "2",
"customer_detail": [{
"room_number": "1",
"salutation": "Mr",
"first_name": "test",
"last_name": "test",
}, {
"room_number": "1",
"salutation": "Mr",
"first_name": "test2",
"last_name": "test2",
}],
}

Related

How to disable labels for additional properties with react-jsonschema-form?

I am trying to use this playground to find a schema which will allow me to show an object addable custom properties (basically I want the user to enter an associative array).
When I do this:
{
"title": "My object",
"type": "object",
"additionalProperties": true
}
I get this
But I don't want the titles "newKey Key" and "newKey" to show.
I tried disabling labels in the uischema
{
"additionalProperties": {
"ui:label": false
}
}
But that only disables them for the values, not the keys
How do I get rid of the "newKey Key"?
I solved this problem using a CSS stylesheet. In the uiSchema, you can give a unique className to the additionalProperties. For example, here I used hidden-title as my additional class:
{
'uiSchema': {
"title": "My object",
"type": "object",
'additionalProperties': {
'ui:label': False,
'classNames': 'hidden-title'
}
}
}
Then, your html is rendered with the new className as part of the parent form-group div:
<div class="form-group field field-string hidden-title">
<div class="row">
<div class="col-xs-5 form-additional">
<div class="form-group">
<label class="control-label" for="root_new-key">new key</label>
<input class="form-control" type="text" id="root_new-key" value="new key">
</div>
</div>
<div class="form-additional form-group col-xs-5">
<input class="form-control" id="root_new-key" label="new key" placeholder="" type="text" value="">
</div>
<div class="col-xs-2">
<button type="button" class="btn btn-danger array-item-remove btn-block" tabindex="-1" style="border: 0px;">
<i class="glyphicon glyphicon-remove"></i>
</button>
</div>
</div>
</div>
Lastly, we can set our CSS to display: none; for any classes matching the unique className we defined. Note that this new className has only been applied to the additionalProperties of your object, not any pre-defined properties.
.hidden-title label.control-label {
display: none;
}
The documentation was a little confusing on this point, since it seems to imply that 'ui:label': False will cover both labels. As you pointed out, it only hides the value label (not the key label).
You don't need additionalProperties, use below code:
{
schema: {
newKey: {
type: "string"
}
},
uiSchema: {
newKey: {
"ui:widget": "select2",
"ui:options": {
label: false
}
}
}

Using angular ui-bootstrap and typeahead selection

I have a project where I am trying to use Typeahead (ui.bootstrap.typeahead) from http://angular-ui.github.io/bootstrap/
I have a select loading data options from a remote server(data1.json).
When the user type into select, I´d like to show on dropdown something with the format "Acrelandia - AC"(the format is cityname+' - ' +id), and the ng-model needs contain the next data:{city:'Acrelandia',state:'AC'}
Of course, The seleted text needs to be something as: "Acrelandia - AC"
I have tried the next but, I don´t know how format the result from promise to my requirements. It shows all cities in wrong format.
js:
data1:json:
{
"state": [
{
"id": "AC",
"name": "Acre",
"city": [
"Acrelandia",
"Assis Brasil",
"Brasileia",
]
},
{
"id": "AL",
"name": "Alagoas",
"city": [
"Agua Branca",
"Anadia",
"Vicosa"
]
}
]
}
js:
app.controller('infoController',['$scope','$http',function($scope,$http){
$scope.getLocation = function(val) {
return $http.get('/data1.json', {
params: {
address: val,
sensor: false
}
}).then(function(response){
return response.data.estados.map(function(item){
return item.cidades.toString();
});
});
};
Markup:
<div class="input-group ">
<input type="text" ng-model="customerCity" placeholder="Type something" uib-typeahead="address for address in getLocation($viewValue)" typeahead-loading="loadingLocations" typeahead-no-results="noResults" class="form-control">
<i ng-show="loadingLocations" class="glyphicon glyphicon-refresh"></i>
<div ng-show="noResults">
<i class="glyphicon glyphicon-remove"></i> No Results found
</div>
</div>

Angular 2 nested form group contains null values

I'm working with a nested form group structure with Angular 2 beta "FormBuilder" and for the life of me I can't get values into the nested form group. It's weird because binding works just fine. I can send a "user" object to the form and it fills in all the values for the user and their address. But when sending the form value out (say, to an HttpPost), it looks just like the object below...
FWIW I'm following Mosh Hamedani's excellent Angluar 2 course on Udemy and have checked and double checked that the relevant code matches his here: https://github.com/mosh-hamedani/angular2-course
Perhaps what I need is to be told where else to look in my code?
Here's my form group as shown by placing {{ form.value | json }} at the end of my form:
{
"name": "Leanne Graham",
"email": "Sincere#april.biz",
"phone": "1-770-736-8031 x56442",
"address": {
"street": null,
"suite": null,
"city": null,
"zipcode": null
}
}
this is the constructor in my component:
constructor(
fb: FormBuilder,
private router: Router,
private usersService: UsersService,
private params: RouteParams
){
this.form = fb.group({
name: ['', Validators.required],
email: ['', EmailValidators.mustBeEmail], // I hadn't considered the obvious: if it doesn't exist it also doesn't qualify as email.
phone: [],
address: fb.group({
street: [],
suite: [],
city: [],
zipcode: []
})
});
}
This is the form in my template (truncated for brevity):
<div class="col-md-6 well">
<!--the "fieldset" element is needed for this kind of grouped layout.-->
<form [ngFormModel]="form" (ngSubmit)="save()">
<fieldset>
<legend>User</legend>
<div class="form-group">
<label>Name</label>
<input type="text" [(ngModel)]="user.name" ngControl="name" #name="ngForm" class="form-control">
<div class="alert alert-danger" *ngIf="name.errors && name.touched">
The user name is required.
</div>
</div>
*** Email and Phone similar ***
</fieldset>
<fieldset ngControlGroup="address">
<legend>Address</legend>
<div class="form-group">
<label>Street</label>
<input type="text" [(ngModel)]="user.address.street" ng-control="street" class="form-control">
</div>
*** suite, city, and zip similar ***
</fieldset>
{{ form.value | json }}
<button [disabled]="!form.valid" class="btn btn-primary" type="submit">Save</button>
</form>
</div>
ng-control="street"
should be
ngControl="street"
like you did with name

Binding to correct model - with same name

I have an ng-repeat that displays 2 forms (the array has 2 items)
I have an empty input for each of these, that has the same model, something like the following:
<div ng-repeat=“group in groups”>
<form>
<input type=“text” ng-model=“group.name” placeholder=“name” />
</form>
</div>
Now this works well, until I try to enter text into the first input, it automatically enters into the second as well.
Is there an easy way to bind to the input i’m actually typing in?
Thanks
Your PLNKR example doesn't match your question.
Simplifying your code:
<!-- Top loop doesn't repeat -->
<div ng-repeat="group in groups">
<div ng-repeat="g in group">
<div ng-repeat="info in g.info.data">
<input ng-model="info.name" placeholder="Name" />
</div>
<!-- This is the problem -->
<input ng-model="test.name" placeholder="Name">
<button ng-click="nameAdd($parent.$index)">
Add
</button>
</div>
</div>
The input with the Add button uses the same ng-model name. Also here are three nested loops when only two are needed.
The Data
$scope.groups = {
"data": [{
"id": 1,
"name": "Group 1",
"site_id": 3,
"info": {
"data": [{
"id": 1,
"name": "Jim"
}]
}
}, {
"id": 2,
"name": "Group 2",
"site_id": 3,
"info": {
"data": [{
"id": 10,
"name": "Bob"
}, {
"id": 11,
"name": "Terry"
}]
}
}]
}
Change the template to:
<!-- remove top loop
<div ng-repeat="group in groups">
-->
<div ng-repeat="groupDatum in groups.data" ng-cloak>
<div ng-repeat="infoDatum in groupDatum.info.data">
<input ng-model="infoDatum.name" placeholder="Name" />
</div>
<!-- use groupDatum to store new name -->
<input ng-model="groupDatum.newName" placeholder="Name">
<!-- use groupDatum as arg to ng-click -->
<button ng-click="nameAdd(groupDatum)">
Add
</button>
</div>
The nameAdd function:
$scope.nameAdd = function(groupDatum) {
var newId = uniqueId();
var newName = groupDatum.newName;
groupDatum.info.data.push({id: newId, name: newName});
}
try like this,
<div ng-repeat=“group in groups”>
<form>
<input type=“text” ng-model=“groups[$index].name” placeholder=“name” />
</form>
</div>
you also probably put the form tag outside of the repeater unless you want to create a new from for every input tag

Label value selected in angularJs drop down list

I had a label containing value user.Rules e.g . London
<label id="ruleId" for="Rules" ng-model="user.Rules" ng-hide="editmode"
style="width:97%; word-wrap:break-word; overflow-wrap:break-word;">{{user.Rules }}
</label>
After click on edit button a drop down list appears containing the list of states e,g Delhi, Pune, London etc.,
<select class="form-control" name="user.Rules" data-ng-model="user.Rules" ng-options="option for option in nestedList" ng-show="editmode" style="width:100%; ">
<option value="" style="margin-left:25px">-Select Rule-</option>
</select>
I need to set the selected value as the label value of drop down list i.e. London
How can I do that ?
Since there is no sample code and sample data for nestedList is not available, so I assume the data as my own and created this sample.
I consider the $scope.RuleId contains the id from the database. I removed the ng-model="user.Rules" from the label and and based on the $scope.RuleId I find its equivalent value.
HTML Code:
<div ng-controller="MyCntrl">
<label id="ruleId" for="Rules" ng-hide="editmode"
style="width:97%; word-wrap:break-word; overflow-wrap:break-word;">{{selectedLabel}}
</label>
<select class="form-control" name="ruleDetails" data-ng-model="RuleId"
ng-options="option.RuleId as option.Rules for option in nestedList"
ng-show="editmode" style="width: 100%;">
<option value="" style="margin-left:25px">-Select Rule-</option>
</select>
<div style="height: 10px"></div>
<div>
<button ng-click="editButton()">Edit</button>
</div>
</div>
Controller Code:
function MyCntrl($scope) {
$scope.editmode = false;
$scope.RuleId = "001";
$scope.nestedList = [{
"Rules": "London",
"RuleId": "001"
}, {
"Rules": "Delhi",
"RuleId": "002"
}, {
"Rules": "Pune",
"RuleId": "003"
}, {
"Rules": "Mumbai",
"RuleId": "004"
}, {
"Rules": "Chennai",
"RuleId": "005"
}];
angular.forEach($scope.nestedList, function(rule) {
if (rule.RuleId === $scope.RuleId) {
$scope.selectedLabel = rule.Rules;
}
});
$scope.editButton = function() {
$scope.editmode = true;
};
}
The same code is added in the Working Sample for your reference.

Resources