how to display items with category name as title - reactjs

hi I have multiple items with different categories. I want to display all item with its Category name as a title at header. My code displaying each item but category Title repeats with each item.
I want Category title only one time at the top and then its items list.
MY Code is this
{
formsList.map((item, index,temp=0) => {
if(temp!==item.cat_id)
{
temp = item?.cat_id;
return (
<div className="custom-control custom-radio mb-3">
<div className="form-control-label"> {item.category_title}</div>
<input
className="custom-control-input"
id= {item.id}
name= {item.cat_id}
type="radio"
/>
<label className="custom-control-label" htmlFor={item.id}>
{item.form_title} {temp}
</label>
</div>
)
}
return (
<div className="custom-control custom-radio mb-3">
<input
className="custom-control-input"
id= {item.id}
name= {item.cat_id}
type="radio"
/>
<label className="custom-control-label" htmlFor={item.id}>
{item.form_title}
</label>
</div>
)
})
}
My Json array is like this.
{"forms":
[
{"id":1,"category_title":"Individual Tax Return","cat_id":1,
"form_title":"Single},
{"id":2,"category_title":"Individual Tax Return","cat_id":1,
"form_title":"Married Filing Separately"},
{"id":3,"category_title":"Business Type", "cat_id":2,
"form_title":"SoleProprietorships"},
{"id":4,"category_title":"Business Type","cat_id":2,
"form_title":" Partnership"}
]
}
I want to display this one like as below
//////////////////
Individual Tax Return
Single
Married Filing Separately
Business Type
SoleProprietorships
Partnership
/////////////////////////
Please check and help with thanks

Please try this
json part
const recipes = [{
id: 716429,
title: "Pasta with Garlic, Scallions, Cauliflower & Breadcrumbs",
image: "http://ovuets.com/uploads/716429-312x231.jpg>",
dishTypes: [
"lunch",
"main course",
"main dish",
"dinner"
],
recipe: {
// recipe data
}
}]
function part
export default function Recipes() {
return (
<div>
{recipes.map((recipe) => {
return <div key={recipe.id}>
<h1>{recipe.title}</h1>
<img src={recipe.image} alt="recipe image" />
{recipe.dishTypes.map((type, index) => {
return <span key={index}>{type}</span>
})}
</div>
})}
</div>
)}

Related

Disable all checkboxes except "checked" react hooks

I have listing of products and user can compare upto 4 products, when user checked 4 products I want to disable all checkboxes so user cannot select other product for compare until unless it uncheck one of 4 checkboxes.
const [checkedddItems, setCheckedItems] = useState({checkedItems : {}})
const handleComparePackage = (e, packageId) => {
const { id, checked } = e.target;
const updatedCheckedItems = comparedPackages.includes(packageId)? { [id]: checked } : {checkedddItems, [id] : checked }
console.log(updatedCheckedItems);
setCheckedItems({checkedItems: updatedCheckedItems})
}
{ insurancePackages.map((insPackage) => {
return (
<div className="col-lg-3 col-md-4 col-sm-6" key={insPackage.id}>
<div className="insurance-card active">
{compareSwitch &&
<div className="form-check">
<input
className="form-check-input"
type="checkbox"
id={insPackage.id}
checked={checkedddItems[insPackage.id]}
disabled={!checkedddItems[insPackage.id]}
onChange={(e) => { handleComparePackage(e, insPackage.id) }} />
</div>
}
<div className="thumb">
<img src="/insurance/logo.svg" alt="logo" />
</div>
<div className="title">
{insPackage.company.name}
</div>
<div className="text-detail">
{insPackage.description}
<br />
<Link href="/">
<a>View Package Details</a>
</Link>
</div>
</div>
)
})
}
From what I can tell, it seems like you need some way to disable all checkboxes when the following conditions are met:
the checkbox is not checked,
the amount of total checked items > 3
This should simply turn into a simple boolean statement in the disabled attribute on the checkbox <input/>.
<input
className="form-check-input"
type="checkbox"
id={insPackage.id}
checked={checkedddItems[insPackage.id]}
disabled={!checkedddItems[insPackage.id] && checkedddItems.length > 3} // right here
onChange={(e) => { handleComparePackage(e, insPackage.id) }} />

patchValue returning only values of the last index

I have an issue while looping through and array, I'm getting all the index from this array correctly but when I use angular patchValue it updates all the inputs with the last index values and not with their respective values as shown :
I want every input to have theirs, for example, first input values should be "1" (left input => longueur) and "1" (right input => quantity)
I tried with .forEach but no success
CODE SAMPLE
component.ts .forEach
ngOnInit() {
this.requiredFields();
this.service.checkExistQuot().subscribe(res => {
this.quotDetails.forEach( (myArray, index) => {
this.dropForm.patchValue({
longueur: this.quotDetails[index].longueur,
quantity: this.quotDetails[index].quantity
})
console.log(index);
});
});
}
HTML, input example
<div class="products">
<div class="d-flex flex-row" *ngFor="let products of selectedDiam;let i = index">
<input class="number" formControlName="longueur" value="" (change)="postQuotationDatas(products.part_id)" type="number">
</a>
<input class="mb-1 flex1 checkbox" type="checkbox">
<a class="tac flex1"></a>
<a class="flex1 mb-1">
<input class="number" value="" formControlName="quantity" (change)="postQuotationDatas(products.part_id)" type="number">
</a>
<a class="flex1"></a>
</div>
</div>
Your problem is that you only have one form group,dropForm, with 2 controls: quantity and longueur. Even though you have multiple html inputs for longueur and quantity, they are share the same reference in the component
So, with your forEach loop, you are actually patching all your controls for each iteration. That's why you have the same value for all your controls, which is the value for the lasst object the loop went over.
Option #1
A possible solution is to have multiple form groups, like in this stackblitz example
component.ts
//dropForms initialisation
this.quotationDetails.map(() =>
{
let group = this.formBuilder.group(
{
longueur: [''],
quantity: [''],
});
this.dropForms.push(group)
}
this.quotationDetails.forEach( (myArray, index) => {
this.dropForms[index].patchValue({
longueur: this.quotationDetails[index].longueur,
component.html
<div class="d-flex flex-row" *ngFor="let products of quotationDetails; let index=index">
<form [formGroup]="dropForms[index]"> <!-- 1 form group per quotation -->
Option #2
The other solution, to have only 1 formGroup, is to give dynamic control names
component.ts
//Initialisation of dropForm
this.quotationDetails.forEach((val, index)=>
{
group[`longueur_${index}`] = '';
group[`quantity_${index}`] = ''
});
this.dropForm = this.formBuilder.group(
group
)
//Patch
this.quotationDetails.forEach( (myArray, index) => {
let patchValue = {};
patchValue[`longueur_${index}`] = this.quotationDetails[index].longueur;
patchValue[`quantity_${index}`] = this.quotationDetails[index].quantity;
this.dropForm.patchValue(patchValue);
component.html
<form [formGroup]="dropForm">
<div class="products">
<div class="d-flex flex-row" *ngFor="let products of quotationDetails; let index = index">
<a>
<input class="number" formControlName="longueur_{{index}}" value="" type="number">
Stackblitz example
Use FormArray and wrap inputs in arrays.
Example add FormControl to FormArray with FormBuilder:
FormArray - A FormArray aggregates the values of each child FormControl into an array.
in componenent ts:
const EMPLOYEE_FORM = {
firstName: ['', Validators.required],
lastName: ['', Validators.required],
isActive : [false, Validators.required]
}
const COMPANY_FORM = {
employees: new FormArray([], [Validators.required])
}
export class AppComponent {
form: FormGroup;
constructor(private fb: FormBuilder) {
this.form = this.fb.group(COMPANY_FORM);
}
get employees(): FormArray {
return this.form.get('employees') as FormArray;
}
addEmployee() {
const employee = this.fb.group(EMPLOYEE_FORM);
this.employees.push(employee);
}
}
in html
<div *ngFor="let item of employees.controls; let i = index;">
<form [formGroup]="item">
<input type="text" formControlName="firstName" class="form-control" placeholder="FirstName">
<input type="text" formControlName="lastName" class="form-control" placeholder="LastName">
<input class="checkbox" type="checkbox" formControlName="isActive">
</form>
</div>
<button (click)="addEmployee()">add new employee</button>
<div *ngIf="employees.length > 0">
{{employees.value | json}}
</div>
See this link: https://stackblitz.com/edit/add-input-to-formarray-with-frombuilder

create objects on form submit in typescript angular 7

I am trying to create 2 separate objects on form submission. Below is my code:
test.html
<form [formGroup]="gamificationForm" (ngSubmit)="onSubmit()">
<div *ngFor="let medal of medalResponse; let iMedal=index" class="row col-lg-12 mtop-custom-10 medal-level-point-config">
<input type="hidden" class="point-text" [(ngModel)]="medal.medalId" formControlName="medalId" />
<div class="col-lg-4 col-6">
{{medal.medalName}}
<input type="hidden" class="point-text" [(ngModel)]="medal.medalName" formControlName="medalName" />
</div>
<div class="col-lg-4 col-6">
<input type="number" class="point-text" [(ngModel)]="medal.points" formControlName="points" />
</div>
</div>
<button class="custom-btn-class" name="submit" type="submit">Save</button>
</form>
Typescript:
gamificationForm = this.fb.group({
medals: this.fb.group({
medalId: [''],
medalName: [''],
points: ['']
})
});
onSubmit() {
console.warn(this.gamificationForm.value);
}
JSON:
It is printing last values from the loop on html page and in json too.
You can convert this JSON value to your required format,
format(value) {
return [
{
Level: [
{
"levelId-0":value.levelId-0,
"level-0":value.level-0,
"points-0":value.points-0
},
....
],
Medal: [
.....
]
}
]
}
Unfortunately I haven't done this via Template-driven Forms, but here my ideas:
You will need to group your fields into the Level and Medal arrays by wrapping your *ngFor into a <ng-container formArrayName="Level"> container and try it.
Each *ngFor should set the position FormArray, but you will need to experiment and see if the formArrayName directive does it for you.
Happy ng-coding!

console.log to props breaks when used with its iteration using .map in render method

I have an object I received from a parent component as props. In render method, when printed with console.log prints me the complete object but it prints empty when the same object is being iterated using.map for html tags to print the values.
Cannot understand why this behavior, this is an extension from the question the complete object is available in that question, below is the part of object which is being iterated:
"mlaList": [{
"mlaNo": 92,
"lesseeId": 108,
"executionDate": "27/01/2017",
"signatoryInfo": "Test",
"overdueRate": 3.44,
"nonPaymentDays": 2,
"consolidationTerm": "Monthly",
"createdBy": null,
"createdDtm": null,
"updatedBy": null,
"updatedDtm": null,
"statusIndicator": null,
"signatoryEmail": "tooot#gmail.com",
"leaseMlaNo": "OPM1",
"statusDescription": "APPROVED"
}, {
"mlaNo": 93,
"lesseeId": 108,
"executionDate": "03/01/2017",
"signatoryInfo": "tess",
"overdueRate": 5.77,
"nonPaymentDays": 2,
"consolidationTerm": "Bi-Monthly",
"createdBy": null,
"createdDtm": null,
"updatedBy": null,
"updatedDtm": null,
"statusIndicator": null,
"signatoryEmail": "xyz#gmail.com",
"leaseMlaNo": "OPM2",
"statusDescription": "APPROVED"
}]
below is the component in which render method is also available with the mentioned code:
class AddLesseeInfoMLA extends Component {
constructor(props) {
super(props)
this.handlePrev = this.handlePrev.bind(this)
this.handleNext = this.handleNext.bind(this)
}
handlePrev() {
this.props.changeNavFunction(this.props.prevStep)
}
handleNext() {
this.props.changeNavFunction(this.props.nextStep)
}
render() {
console.log("Result::"+this.props.data)
return (
<div id="add-facility-info-profile-form-wrapper">
<Validation.components.Form id="add-facility-terms-info-form" ref="form" className="melody-common-form">
<div id="add-facility-terms-info-form">
{this.props.data.mlaList.map((data, index) =>
<div className="add-facility-terms-info-form-wrapper2" key={index}>
<div className="inputContainer melody-common-form-label">
<label className={index === 0 ? '' : 'melody-common-display-none'}>Lease MLA Number</label>
<Validation.components.Input value={data.leaseMlaNo} id="leaseMlaNo" className="short melody-common-input-disabled" type="text" name="leaseMlaNo" ref="leaseMlaNo" disabled="true" />
</div>
<div className="inputContainer melody-common-form-label">
<label className={index === 0 ? '' : 'melody-common-display-none'}>Status</label>
<Validation.components.Input value={data.statusDescription} id="statusDescription" className="short melody-common-input-disabled" type="text" name="statusDescription" ref="statusDescription" disabled="true" />
</div>
<div className="inputContainer melody-common-form-label">
<label className={index === 0 ? '' : 'melody-common-display-none'}>Consolidation Term</label>
<Validation.components.Input value={data.consolidationTerm} id="consolidationTerm" className="short melody-common-input-disabled" type="text" name="consolidationTerm" ref="consolidationTerm" disabled="true" />
</div>
<div className="inputContainer melody-common-form-label">
<label className={index === 0 ? '' : 'melody-common-display-none'}>Overdue Rate (%)</label>
<Validation.components.Input value={dataFormatter.toPercentFormat(data.overdueRate)} id="overdueRate" className="short melody-common-input-disabled" type="text" name="overdueRate" ref="overdueRate" disabled="true" />
</div>
<div className="inputContainer melody-common-form-label">
<label className={index === 0 ? '' : 'melody-common-display-none'}>Non Payment Days</label>
<Validation.components.Input value={data.nonPaymentDays} id="nonPaymentDays" className="short melody-common-input-disabled" type="text" name="nonPaymentDays" ref="nonPaymentDays" disabled="true" />
</div>
</div>
)}
</div>
</Validation.components.Form>
</div>
)
}
}
export default AddLesseeInfoMLA

how to select one primary contact on listing of contacts in ng-repeat by radio button

I have list of contacts and repeating with ng-repeat how to make one primary contact by selecting radio button .
<div class="col-sm-12" ng-repeat='contact in acc.contacts'>
<div class="col-xs-2" ng-class="{'error':(sub && !contact.isPrimary)}">
<input type="radio" name='isPrimary' ng-model='contact.isPrimary' ng-value="true">
</div>
<div class="col-xs-2" ng-class="{'error':(sub && !contact.name)}">
<input type="text" ng-model='contact.name'>
</div>
</div>
</div>
my json is look like
{
"contacts": [
{
"isPrimary": false,
"name": null,
},
{
"isPrimary": false,
"name": null
},
{
"isPrimary": false,
"name": null
]
}
i want isPrimary should be true for one , but it does not set false when radio button got deselected
Because you use the radio button in an ng-repeat and the ng-model is a property of the repeated item, you can do it like this:
<div class="col-xs-2" ng-class="{'error':(sub && !contact.isPrimary)}">
<input type="radio" name='isPrimary'
ng-value="true"
ng-change="primaryClicked(contact)">
</div>
And in your controller:
$scope.primaryClicked = function(contact) {
// Set all others on false
for (var i = 0; i < $scope.acc.contacts.length; i++) {
$scope.acc.contacts[i].isPrimary = false;
}
// Set current on true
contact.isPrimary = true;
}
The correct approach is to use ng-value.
Modify your code:
<label data-ng-repeat="contact in acc.contacts">
<input type="radio" data-ng-model="contact.isPrimary" data-ng-value="true" />
{{contact.name}}
</label>
Hope this is helps you

Resources