primeng checkbox with reactive form with array - javascript

I am trying to add my array of object to map the primeng checkbox and would like to get the values for selected check boxes.
I have tried FormControlName but it it's throwing undefined after submitting.
below is the rough code
data = [
{ type: dropdown
text: 'drop',
num: 1.23,
options: [
{
value=1,
text= 'drop1
},{
value=2,
text= 'drop2
}
]
},
{ type: checkbox
text: 'check',
num: 1.23,
options: [
{
value=1,
text= 'check1
},{
value=2,
text= 'check2
}
]
},
{ type: radio
text: 'radio',
num: 1.23,
options: [
{
value=1,
text= 'radio1
},{
value=2,
text= 'radio2
}
]
},
];
Template:
<form [formGroup]="group">
<div *ngFor="let d of data">
<div *ngSwitchCase = "checkbox">
<p-checkbox *ngFor="let check of options" [value]="check.value" [formControlName]="check.text"></p-checkbox>
</div>
<div *ngSwitchCase = "dropdown">
<p-dropdown *ngFor="let drop of options" [value]="drop.value" [formControlName]="d.text"> {{drop.text}}
</p-dropdown>
</div>
<div *ngSwitchCase = "radio">
<p-radioButton *ngFor="let radio of options"[value]="radio.value" [formControlName]="d.text"></p-radioButton >
</div>
</div>
</form>
How I can get the reference of my control and values the same for drop down and check boxes.
How to get the values for dynamic forms?

for reactive dynamic form first thing we have to generate the formGroup base of the form control data
getFormGroup method will return a formGroup object by loop over the data and create a form controls with name base of the text value .
getFormGroup() {
const formControls = this.data.reduce( (controls , f:FormControl)=>{
controls[f.text] = this.formBuilder.control(null);
return controls;
},{});
return this.formBuilder.group(formControls)
}
after we generate the form now we can render the form controls on the template
<form [formGroup]="form">
<div *ngFor="let d of data">
<ng-container [ngSwitch]="d.type">
<label for="">{{d.text}}</label>
<div *ngSwitchCase="'checkbox'">
<p-checkbox *ngFor="let check of d.options" [label]="check.label" [value]="check.value"
[formControlName]="d.text"></p-checkbox>
</div>
<div *ngSwitchCase="'dropdown'">
<p-dropdown [options]="d.options" [formControlName]="d.text">
</p-dropdown>
</div>
<div *ngSwitchCase="'radio'">
<p-radioButton *ngFor="let radio of d.options" [name]="d.text" [label]="radio.label"
[value]="radio.value" [formControlName]="d.text">
</p-radioButton>
</div>
</ng-container>
</div>
</form>
stackblitz demo 🚀

Related

How to generate dynamic tab with data based on API in Angular8

I have below JSON response.
From JSON response i am creating dynamic tab and inside every tab i want to push formArray based on below mentioned condition.
**In below response,
const myObj = [
{
'TabName': 'Test1',
'otherDetails': [
{
'processTechType': 'Continuous'
},
{
'processTechType': 'Batch',
},
]
},
{
'TabName': 'Test2',
'otherDetails': [
{
'processTechType': 'Batch'
}
]
}
];
For Ex - TabName Test1 and TabName Test2 are tabs name which i am displaying dynamically. Now in Test1 Tab, i want to push formArray Continuous and formArray Batch both forms. Because in Test1 Tab, i have processTechType array with Continuous and batch both. So it will show both form in Test1 Tab.
Ex - 2 -- Now in Test2 Tab, i want to push formArray Batch form only. Becuase in Test2 Tab, i have processTechType batch in otherDetails object. So it will show Batch form only in Test2 Tab.
My mean to say is everytime it will check the Tabname and otherDetails key from response and show forms based on processTechType array key on specific tab only.
I have below code. But it is pushing both forms in all tabs, not on specific tab. For ex - From my code, It is showing Continuous formArray onetime and Batch formArray two times in Test1 and Test2 tabs both.
Expected output -
In Test1 Tab, it will push one Continuous and one Batch form.
In Test2 Tab, It will show push batch form only.
Can anyone please help me get my code work to get my expected output.
getMakeLineData() {
var otherDetails = myObj.filter(m => m.otherDetails).map(m => m.otherDetails);
this.makeLineData = myObj;
if (otherDetails) {
otherDetails.forEach(element => {
for (var i of element) {
if (i.processTechType === 'Continuous') {
this.addQuantity();
}
else if (i.processTechType === 'Batch') {
this.addBatch();
}
}
});
}
}
createContinuousForm() {
return this.fb.group({
designProcess: ['', [Validators.required]]
});
}
createBatchForm() {
return this.fb.group({
avgBCT: ['', [Validators.required]]
});
}
continuousType(): FormArray {
return this.dataCollectionForm.get("continuousType") as FormArray;
}
batchType(): FormArray {
return this.dataCollectionForm.get("batchType") as FormArray;
}
addQuantity() {
this.continuousType().push(this.createContinuousForm());
}
addBatch() {
this.batchType().push(this.createBatchForm());
}
HTML Template
<div class="tabGroupDiv row">
<div class="lossLinesDiv">
<mat-tab-group class="lossMatGrpCls" mat-align-tabs="left">
<mat-tab *ngFor="let lineData of makeLineData">
<ng-template mat-tab-label>
<button class="validatorTabBgClr">{{lineData.makeLineName}}</button>
</ng-template>
<form [formGroup]="dataCollectionForm" (ngSubmit)="onSubmit()">
<!-- <--continuous Form start here -->
<div class="admin-console-main-wrapper" formArrayName="continuousType">
<div class="content-wrapper" *ngFor="let lineItem of continuousType().controls; let i=index"
[formGroupName]="i">
<div class="row list-wrapper">
<div class="col-xs-3 col-md-3 deo-dv-list-wrapper">
<h5 class="topbar-items-text">Design Process Capacity (Tonnes)</h5>
<mat-form-field appearance="outline">
<input matInput type="text" class="line-fte-input smed-input" placeholder="Design Process Capacity"
formControlName="designProcess">
</mat-form-field>
<mat-error *ngIf="lineItem?.controls?.designProcess?.hasError('required')">
Field is required
</mat-error>
</div>
</div>
</div>
</div>
<!-- <--continuous Form start here -->
<!-- <--Batch Form start here -->
<div class="admin-console-main-wrapper" formArrayName="batchType">
<div class="content-wrapper" *ngFor="let lineBatchItem of batchType().controls; let i=index"
[formGroupName]="i">
<div class="row list-wrapper">
<div class="col-xs-3 col-md-3 deo-dv-list-wrapper">
<h5 class="topbar-items-text">Average BCT (mins)</h5>
<mat-form-field appearance="outline">
<input matInput type="text" class="line-fte-input smed-input" placeholder="Average BCT"
formControlName="avgBCT">
</mat-form-field>
</div>
</div>
</div>
</div>
<!-- <--Batch Form ends here -->
</form>
</mat-tab>
</mat-tab-group>
</div>
</div>
Your object is complex to relationa tabs and FormArrays, So, imagine you has a more confortable object. Some like
[{tabName:'Tab 1',continuousType:0,batchType:0},
{tabName:'Tab 2',continuousType:1,batchType:-1}]
See that you use "-1" to indicate the tab has no a form of this type
For this create a function thah return this more confortable array
tabsConfig(obj:any){
const tab=[];
let continuousType=0;
let batchType=0;
obj.forEach((x,index)=>{
tab[index]={tabName:x.TabName,continuousType:-1,batchType:-1}
x.otherDetails.forEach(y=>{
if (y.processTechType=='Continuous')
tab[index].continuousType=continuousType++
if (y.processTechType=='Batch')
tab[index].batchType=batchType++
})
})
return tab
}
Now you can use a variable to store the config
this.tabs=this.tabConfig(this.myObj)
You can then
this.tabs.forEach(x=>{
if (x.continuousType!=-1)
this.continuousType.push(this.createContinuousForm())
if (x.batchType!=-1)
this.batchType.push(this.createBatchForm())
})
And, if you has two auxiliars forms that return the formGroup of the of the FormArrays
getContinuousForm(index:number){
return (this.dataCollectionForm.get("continuousType") as FormArray)
.at(index) as FormGroup
}
getBatchForm(index:number){
return (this.dataCollectionForm.get("batchType") as FormArray)
.at(index) as FormGroup
}
You're ready to create the mat-tab iterating over the "tabs" array
<mat-tab-group >
<mat-tab *ngFor="let tab of tabs;let i=index">
<ng-template mat-tab-label>
<button >{{tab.tabName}}</button>
</ng-template>
<form *ngIf="tab.continuousType!=-1
[formGroup]="getContinuousForm(tab.continuousType)">
....
</form>
<form *ngIf="tab.batchType!=-1
[formGroup]="getBatchForm(tab.batchType)">
....
</form>
</mat-tab>
</mat-tab-group>

How to Pass id and name from the first form, and Show only the name in second form in angularjs

I Have two forms.In these forms am getting input from the first form and show that in the second form, Which means if the user selected the currency from the dropdown, i need to pass id and the the currency name. But show only the currency name in the second form. I tried one method (dont know whether it is correct or not) it is showing the id only. am new to angular. is there anyway to solve this?
HTML
<div class="row text-center" ng-show="firstform">
<form name="validation">
<label>Currency</label>
<select ng-model="CurrencyId" ng-selected="CurrencyId" class="form-control" id="CurrencyId">
<option ng:repeat="CurrencyId in currencyList" ng-selected="selectedCurrencyType == CurrencyId.id" value={{CurrencyId.currencyId}}>{{CurrencyId.name}}</option>
</select>
<label>Grade</label>
<select ng-model="GradeId" ng-selected="GradeId" class="form-control" id="GradeId">
<option ng:repeat="GradeId in RaceGradeList" ng-selected="selectedGrade == GradeId.id" value={{GradeId.id}}>{{GradeId.gradeName}}</option>
</select>
<button type="submit"value="add" ng-click="savedetails()" />
</form>
</div>
<div class="row text-center" ng-show="secondform">
<form name="thirdform">
<ul >
<li><p>Currency:{{CurrencyId}}</p> </li>
<li><p>Grade:{{GradeId}}</p> </li>
</ul>
</form>
</div>
angular controller
$scope.savedetails = function () {
$scope.firstform= false;
$scope.secondform = true;
}
This is the most simplest solution that you can go for. Instead of having the value={{CurrencyId.currencyId}} set it as value={{CurrencyId.name}} for the options in the dropdown and you are good to go. Below is the demo for the same. But if you want to save currencyId as the value then you will have to iterate over the array and find the name based on the selected currencyId and then show that in the view.
UPDATE
Updated the code to have the currencyId being stored as the selected value and then based on that showing the name in the view.
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope) {
$scope.currencyList = [{
currencyId: 1,
name: "INR"
},
{
currencyId: 2,
name: "$"
},
{
currencyId: 3,
name: "#"
}
];
$scope.currencyChanged = function() {
var selectedCurrency;
for (var i = 0; i < $scope.currencyList.length; i++) {
var thisCurr = $scope.currencyList[i];
if ($scope.CurrencyId == thisCurr.currencyId)
selectedCurrency = thisCurr.name;
}
return selectedCurrency;
}
$scope.firstform = true;
$scope.savedetails = function() {
$scope.firstform = false;
$scope.secondform = true;
}
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<body ng-app="myApp" ng-controller="myCtrl">
<div class="row text-center" ng-show="firstform">
<form name="validation">
<label>Currency</label>
<select ng-model="CurrencyId" ng-selected="CurrencyId" class="form-control" id="CurrencyId">
<option ng:repeat="CurrencyId in currencyList" ng-selected="CurrencyId == CurrencyId.currencyId" value={{CurrencyId.currencyId}}>{{CurrencyId.name}}</option>
</select>
<button type="button" value="add" ng-click="savedetails()">Save Details</button>
</form>
</div>
<div class="row text-center" ng-show="secondform">
<form name="thirdform">
<ul>
<li>
<p>Currency:{{currencyChanged()}}</p>
</li>
</ul>
</form>
</div>
</body>
Hope it helps :)
You can use ng-options , its very flexiable where we can display one value and select either entire object or any specific property.
Please check below plunker , hope it meets your requirement
https://plnkr.co/edit/JQjmAwk62R8rfAlTZ696?p=preview
<select ng-model="CurrencyId" ng-options="currency.id for currency in currencyList" class="form-control" id="CurrencyId" >
</select>
For more details on ng-options , go through below video
https://www.youtube.com/watch?v=vqx3zCy4d3I
try
<li><p>Currency:{{CurrencyId.name}</p> </li>

javascript to hide and show the grids based on the radio button selected and click on search button

I am working on angularjs application. Being a newbie facing issues when trying to get the below mentioned scenario.Any suggestions would be helpful.
I want to display one or two angular UI grid's based on the radio button selected at top. When user selects Show one Grid radio button and type Atlanta in From text field and Chicago in To text field and click on SearchLocations button the first angularjs ui grid should be displayed. Similarly when user selects Show two Grids radio button and type Atlanta in From and Chicago in To text field and click on SearchLocations button, two grids should be shown.
Please find the demo here.
HTML code:
<div>
<label>
Show one Grid <input type="radio" name="Passport" ng-click="ShowPassport('Y')" /></label>
<label>Show two Grids <input type="radio" name="Passport" ng-click="ShowPassport('N')" />
</label>
</div>
<div class="row">
<div class="form-group" ng-controller="citiesCtrl">
<label>From</label>
<input type="text" ng-model="places[0]" placeholder="Type Departure City" typeahead="item for item in items | filter:$viewValue | limitTo:8">
</div>
<div class="form-group" ng-controller="citiesCtrl">
<label>To</label>
<input type="text" ng-model="places[1]" placeholder="Type Destination City" typeahead="item for item in items | filter:$viewValue | limitTo:8">
</div>
</div>
<input type="button" value="SearchLocations" ng-click="submit()">
<div ng-repeat="user in users | filter: {name: searchValue} : true ">
<h3>First Grid</h3>
<div ui-grid="{ data: user.details }" ng-show="user.show" class="myGrid"></div>
</div>
<div ng-repeat="user in users | filter: {name: searchValue} : true ">
<h3>Second Grid</h3>
<div ui-grid="{ data: user.details }" ng-show="user.show" class="myGrid"></div>
</div>
js code:
angular.module('myApp', ['ngAnimate', 'ui.bootstrap','ngTouch', 'ui.grid', 'ui.grid.selection', 'ui.grid.edit','ui.grid.cellNav']);
angular.module('myApp').controller('citiesCtrl',function($scope){
// $scope. places = undefined;
$scope.items = ["Atlanta", "Chicago", "NewYork"];
$scope.selectAction = function() {
console.log($scope.places1);
};
});
/*Controller for searchLocations button*/
angular.module('myApp').controller('searchController', ['$scope', function($scope) {
$scope.places = ['', ''];
$scope.searchValue = '';
$scope.submit = function() {
if ($scope.places[0].length > 0 && $scope.places[1].length > 0) {
$scope.searchValue = $scope.places[0] + $scope.places[1];
}
};
$scope.users = [
{'name' : 'AtlantaChicago',
'show' : true,
'details' : [
{"Travel Date": "10/10/2014", commute:"Bus"},
{"Travel Date": "10/11/2014", commute:"flight"}]
},
{'name' : 'NewYorkChicago',
'show' : true,
'details': [
{"Travel Date": "3/15/2016", commute:"flight"},
{"Travel Date": "10/12/2016", commute:"flight"},
]
}
];
$scope.gridOptions = {
enableFiltering: true,
columnDefs: [
{ name: 'Travel Date', width: '5%'},
{ name: 'Departurecommute', enableFiltering: false, width: '12%' }
],
rowHeight: 20,
enableHorizontalScrollbar:2
};
}]);
You need to change few things in order to get it working as you expected.
If you want to display grids based on radio button selection:
1. you should assign ng-model and value to your radio buttons. Radio buttons in Angular
<label>
Show one Grid
<input type="radio" name="Passport" ng-model="Passport" value=1 ng-click="ShowPassport('Y')" />
</label>
<label>Show two Grids
<input type="radio" name="Passport" ng-model="Passport" value=2 ng-click="ShowPassport('N')" />
</label>
2.Assign the Passport value to another variable on button click. Show hide using Angular
$scope.submit = function() {
$scope.showGrid = $scope.Passport; //Here
if ($scope.places[0].length > 0 && $scope.places[1].length > 0) {
$scope.searchValue = $scope.places[0] + $scope.places[1];
}
};
3.Wrap your grids in a div and assign ng-show attribute
<div ng-show="showGrid==='1'||showGrid==='2'"> //first grid
<div ng-show="showGrid==='2'"> //second grid
4.Now it should work. See the Working plnkr
refer this sample code. you can easily understand
Sample Code
https://codepen.io/SusanneLundblad/pen/iBhoJ

How to hide content with ng-if and a checkbox that's inside a ng-repeat and it's ng-model is an array

I have a list of checkboxes that are created using a ng-repeat, I use those checkboxes to get the IDs of the objects that are inside a list, these objects have a name property and a id property.
this is a object inside my categoryList
category = {
idCategory: 2,
name: 'myName'
};
And this is how I declare my checkboxes.
<div class="form-group">
<label>Select a category</label>
<label class="checkbox-inline" ng-repeat="category in categoryList">
<input type="checkbox" ng-model="idsCategory[category.idCategory]"> {{category.name}}
</label>
</div>
and then in my controller I get the ids like this
var categories= $scope.categoryList;
var idsSelected = [];
//get selected ids
for (var idCategory in categories) {
if (categories.hasOwnProperty(idCategory )) {
if (categories[idCategory ] === true) {
idsSelected .push(idCategory);
}
}
}
but now I want to hide and show some inputs in my HTML, if the user selects a category like "support" I want to show some inputs, but I don't know what condition put inside my ng-if since I declare my checkboxes ng-model like an array of ids like this ng-model="idsCategory[category.idCategory]"
how can I put my ng-if to hide the inputs I tried this but this doesn't work
<div id="b" ng-if="idsCategory.category.name=='Support'">
<div class="form-group">
<label>Support hours:</label>
<input class="form-control" placeholder="support houres">
</div>
</div>
Edited:
If we have HTML:
<div class="form-group">
<label>Select a category</label>
<label class="checkbox-inline" ng-repeat="category in categoryList">
<input type="checkbox" ng-model="idsCategory[category.idCategory]"> {{category.name}}
</label>
</div>
Conroller:
$scope.idsCategory = {};
$scope.categoryList = [{
idCategory: 1,
name: 'categoryA'
}, {
idCategory: 2,
name: 'recreation'
}, {
idCategory: 3,
name: 'develop'
}, {
idCategory: 4,
name: 'Support'
}];
Then we can use following ng-show:
<div id="b" ng-show="idsCategory[4]">
<div class="form-group">
<label>Support hours:</label>
<input class="form-control" placeholder="support houres">
</div>
</div>
See jsfiddle
In checkbox input we have ng-model="idsCategory[category.idCategory]", so idsCategory[4] stores info if category with idCategory = 4 is checked. That's why element with ng-show="idsCategory[4]" will be shown if category with idCategory = 4 is checked.

Angularjs: input for ng-repeat elements

Sorry for my language skills, hope you understand all.
I need to make inputs for ng-repeat elements, to pass input data to http post.
For example: i have 4 elements, for all elements i make inputs, and f.e:
elem1- input: 1
elem2- input: 4
elem3- input: 1
elem4- input: 2
Here is my code:
.panel-body.note-link ng-repeat=("meal in mealsList track by $index")
a data-toggle="tab"
h4.pull-right.text-muted
| {{meal.price}} zł
h4.text-success
i.fa.fa-close.text-danger<> ng-click="removeMeal($index)" style="cursor: pointer;font-size: 15px;"
| {{meal.name}} {{$index}}
input.form-control type="number" ng-model="example"
| {{example}}
And i dont know, how to pass input data to controller.
Any tips,tricks?
angular.module('yourModule').controller('viewController', function($scope) {
$scope.mealList = [...];
$scope.example; //The input data will automatically bind to this variable.
});
If you want the input to change data within your meal object, then do this:
input.form-control type="number" ng-model="meal.example"
And then the property value of the meal object would bind to the input
Repeat through your mealList array and add the inputs.
Example: https://jsfiddle.net/ptzhL0uL/
Controller
function Controller1($scope) {
var vm = this;
vm.items_saved = false;
vm.mealList = [{
price: '2.99',
name: 'Pizza'
}, {
price: '1.99',
name: 'Chips'
}, {
price: '4.99',
name: 'Beer'
}];
vm.addNewItem = addNewItem;
vm.saveItems = saveItems;
function addNewItem() {
vm.mealList.push({});
}
function saveItems() {
vm.items_saved = true;
}
}
HTML
<button ng-click="ctrl.addNewItem()" class="btn btn-default">Add Item</button>
<div ng-repeat="item in ctrl.mealList">
<input type="text" ng-model="item.name">
<input type="text" ng-model="item.price">
<input type="number" ng-model="item.quantity">
</div>
<button ng-click="ctrl.saveItems()" class="btn btn-primary">Save</button>
<hr>
<div ng-if="ctrl.items_saved">
<h4>Here is your meal list:</h4>
<ul>
<li ng-repeat="item in ctrl.mealList">{{item.quantity}}{{item.name}} at ${{item.price}} each</li>
</ul>
</div>
Just attach it to the ngModel directive.
<div ng-repeat="item in array">
{{ item.output }}
<input ng-model="item.output" />
</div>

Categories