Ionic / angular form validation for pick file - html

I am working on an ionic/angular application. My requirement is to pickup files from the device file manager and upload to server after submitting. I did this using the pick file functionality in ionic cordova.
But I'm getting a problem in adding validators to this pickfile. Even without adding files and clicking submit its taking. I want to add required field for this as I added for the subject line.
Below is my code.
HTML file:
<form [formGroup]="sendDocsForm">
<ion-item>
<ion-label>Subject: </ion-label>
<ion-input type="text" formControlName="subject" required></ion-input>
</ion-item>
<div class="error-messages">
<ion-label
*ngIf="sendDocsForm.get('subject').hasError('required') && (signupMobile.get('subject').dirty || signupMobile.get('subject').touched)"
color="danger">
Enter Subject line</ion-label>
</div>
<ion-item>
<div (click)="pickFile()">
<ion-icon name="add"></ion-icon>
<p style="margin:0px;">Add Files</p>
</div>
</div>
<div class="class-addfiles">
<div *ngFor="let item of docPaths; let i=index">
<p (click)="editDocRules(item)">{{ item.name }} </p>
</div>
</div>
Submit
.TS file:
this.sendDocsForm = this.fb.group({
subject: new FormControl ('', Validators.compose([ Validators.required])),
});
pickFile() {
const filter = { mime: 'application/pdf' };
this.fileChooser.open().then(fileuri => {
this.filePath.resolveNativePath(fileuri).then(resolvednativepath => {
console.log(resolvednativepath);
this.returnPath = resolvednativepath;
this.fileName = resolvednativepath.substring(
resolvednativepath.lastIndexOf('/') + 1
);
this.fileType = this.fileName.substring(
this.fileName.lastIndexOf('.') + 1
);
const docPath: ItemDoc = new ItemDoc(
Date.now(),
this.fileName,
this.returnPath
);
this.docPaths.push(docPath);
});
});
}
I want to make the {{item.name}} in the p Tag of the add file as a required field but I don't understand how to do this. Please let me know how I can do this.
Thank you.

Related

Angular 9, how can I use a dynamic input field to get info from a list or array?

I need to get all the strings contained into Assignes array which is a property of Atm object and put them in all the dynamic input, one for each string giving opportunity of updating them or deleting.
How can i do by using FormArray?
atm: Atm; //has an array of string as property
get Assignes() {
return this.virtualForm.get('Assignes') as FormArray;
}
addAssigne() {
this.Assignes.push(this.formBuilder.group({ point: '' }));
}
deleteAssigne(index) {
this.Assignes.removeAt(index);
}
buildForm() {
this.form = new FormGroup({
model: new FormControl(this.atm.Model , Validators.required),
vendor: new FormControl(this.atm.Vendor , Validators.required),
Assignes : this.formBuilder.array([this.formBuilder.group({point : ''})]),
}
<div formArrayName="Assignes">
<div *ngFor="let item of Assignes.controls; let pointIndex=index" [formGroupName]="pointIndex">
<mat-form-field appearance="outline">
<mat-label>Assigne</mat-label>
<input matInput formControlName="point" [readonly]=!isAdmin placeholder="Assigne"/>
</mat-form-field>
<button color="primary" *ngIf="isAdmin" mat-raised-button (click)="deleteAssigne(pointIndex)">Delete assigne</button>
</div>
<button color="primary" *ngIf="isAdmin" mat-raised-button (click)="addAssigne()">Add assigne</button>
</div>
You can do that simply even without using formArray. You just need to run the for loop on the array and render the dynamic input fields.
The code should look like the below:
<div *ngFor="let item of atm; let pointIndex=index" >
<mat-form-field appearance="outline">
<mat-label>Assigne</mat-label>
<input matInput name="assigne{{i}}" [(ngModel)]="item" placeholder="Assigne"/>
</mat-form-field>
<button color="primary" *ngIf="isAdmin" mat-raised-button (click)="deleteAssigne(pointIndex)">Delete assigne</button>
</div>
<button color="primary" *ngIf="isAdmin" mat-raised-button (click)="addAssigne()">Add assigne</button>
The .ts file should get updated by:
atm: Atm; //has an array of string as property
addAssigne() {
this.atm.push('');
}
deleteAssigne(index) {
this.atm.splice(index,1);
}

Why mat-select clear the value in this reactive form?

I´m working on an app like google forms, we have a form with questions, we get these questions from an api and dynamically render the form. the problem is that when i want to add validation to the form with angular reactive forms, the mat-select stops working and every time i select a value, the select is clear.
I already try to adapt this https://medium.com/aubergine-solutions/add-push-and-remove-form-fields-dynamically-to-formarray-with-reactive-forms-in-angular-acf61b4a2afe with no luck
template
<mat-horizontal-stepper [linear]="true" #stepper style="background: transparent">
<mat-step *ngFor="let materia of materias;let m = index;" [stepControl]="createForm(materia.id)">
<ng-template matStepLabel>{{materia.descripcion}}</ng-template>
<form [formGroup]="getForm(materia.id)">
<div fxLayout="column" fxLayoutAlign="space-around stretch" fxLayoutGap="10px">
<div>
<mat-card *ngFor="let competencia of materia.competencias">
<mat-card-header>
<mat-card-title>{{competencia.nombre}}</mat-card-title>
</mat-card-header>
<mat-card-content>
<div fxLayout="column" fxLayoutGap="30px" formArrayName="{{createFormArray(materia.id,competencia.id)}}">
<div fxLayout="row">
<i>{{competencia.descripcion}}</i>
</div>
<div fxLayout="column" fxLayoutGap="2px">
<span *ngFor="let competenciaSimple of competencia.competenciasSimples; let i = index;" fxLayout="row">
<mat-form-field appearance="outline"
*ngIf="competenciaSimple !== null && competenciaSimple !== undefined" fxFlex>
<mat-select (selectionChange)="onSelected($event,competenciaSimple)"
[value]="getSelectedValue(competenciaSimple)" [formControl]="createControl(materia.id,competencia.id)" [id]="i">
<span *ngFor="let fase of competenciaSimple.fases">
<mat-option *ngFor="let conductaObservable of fase.conductasObservables"
[value]="conductaObservable">
{{conductaObservable.descripcion}}
</mat-option>
</span>
</mat-select>
</mat-form-field>
<!-- <input type="hidden" value="competenciaSimple" [(ngModel)]="calificacion.conductasObservables[i].competenciaSimple"/> -->
</span>
</div>
</div>
</mat-card-content>
</mat-card>
</div>
<div fxLayout="row">
<button mat-flat-button type="button" matStepperPrevious *ngIf="!isFirstPage" color="primary"
fxFlex="20">ANTERIOR</button>
<span fxFlex="80"></span>
<button mat-flat-button type="button" *ngIf="!isLastPage" color="primary" fxFlex="20">SIGUIENTE</button>
<button mat-flat-button type="button" (click)="onSubmit()" *ngIf="isLastPage" color="accent"
fxFlex="20">TERMINAR</button>
</div>
</div>
</form>
</mat-step>
</mat-horizontal-stepper>
component.ts
forms = new Array<FormGroup>();
getForm(index: number): FormGroup {
return this.forms[index];
}
createForm(index: number): FormGroup {
const form = this.formBuilder.group({});
this.forms[index] = form;
return form;
}
createFormArray(index: number, name: string): string {
const array = this.formBuilder.array([]);
const arrayName = `competencia_${name}`;
this.forms[index].addControl(arrayName, array);
return arrayName;
}
createControl(index: number, arrayName: string): FormControl {
const control = this.formBuilder.control(false);
const an = `competencia_${arrayName}`;
const array = (this.forms[index].get(an));
(array as FormArray).push(control);
return control;
}
getControlId(): string {
this.controlNumber += 1;
return this.controlNumber.toString()
}
The idea is to validate the mat-select as required so the stepper cant advance when no value is selected, that works if a add the Validator, but the mat-select doesn´t persist the value so if i remove the [formControl]="createControl(materia.id,competencia.id)" the mat-select work but no validation result.
There are several popular open source Angular Form Libraries (you can take a look at the source code and see how they dynamically add validation's to a control):
GitHub: ng-dynamic-forms
GitHub: ngx-formly
GitHub: angular-schema-form (AngularJS) - Generate forms from a JSON schema
GitHub: ngx-schema-form - HTML form generation based on JSON Schema
GitHub: angular2-json-schema-form - Angular 2 JSON Schema Form builder

Do different things in the same function depending on which html component called that function

I am making a basic toggle app in angular.I have two toggle buttons.I am displaying a message in toggle.I want to call the same function on toggle change but do different things depending on which button was toggled.Is it possible or do I have to use two different functions? Thanks in advance for the help.
Here is my template code:
<mat-card class="card" fxLayout="column" fxLayoutAlign="center center" >
<form class="example-form" [formGroup]="formGroup" (ngSubmit)="onFormSubmit()" ngNativeValidate>
<mat-action-list>
<mat-list-item > <mat-slide-toggle
(change)="onChange($event);displayMessage($event)" formControlName="Policy1" >
<span class="label">{{message}}</span></mat-slide-toggle></mat-list-item>
<mat-list-item > <mat-slide-toggle (change)="onChange($event)" formControlName="Policy2">Policy2</mat-slide-toggle></mat-list-item>
</mat-action-list>
<p>Form Group Status: {{ formGroup.status}}</p>
<button mat-raised-button [disabled]="disable" class="button" type="submit">Save Settings</button>
</form>
</mat-card>
The funtion that I'm calling from the toggle button:
displayMessage(e){
if(e.checked)
{
this.message = 'Toggled';
}
else
this.message = 'Slide';
}
The $event object from the (change) emitter has a srcElement that you can refer to when you want to find out which element caused the change.
If you want to retrieve the id of the element that called the function you do so with event.srcElement.id
You can pass more arguments to the handler:
<mat-slide-toggle *ngFor="let item of thingsToDo; let i = index"
(change)= "onToggle($event, item.id, i)">
onToggle = (event, id, indexInArray) => { //...

How to display a array elements in HTML(ionic 3)

I'm new to ionic. Actually, I'm trying to display products added to cart in cart page. I got value from Foreach method, but when I try to display, it won't show.
cartpage(){
this.cart.cartview().then((result) => {
this.cartdisplay = JSON.parse(JSON.stringify(result));
this.categorydata = JSON.parse(JSON.stringify(this.cartdisplay.data));
console.log('result11:'+JSON.stringify(this.categorydata));
var arr = Object.keys(this.categorydata.items);
//this.cartarray =[];
arr.forEach( a =>{
this.cartarray['orderitem_name']= this.categorydata.items[a].orderitem_name;
this.cartarray['orderitem_quantity']= this.categorydata.items[a].orderitem_quantity;
console.log('cart : '+this.cartarray['orderitem_quantity']);
console.log(a) //item id
console.log(this.categorydata.items[a].cart_id) //product id
})
console.log(this.cartarray);
})
}
in the console log, orderitem_name and orderitem_quantity is displaying, but it does not show in the HTML page.
This is my HTML code:
<ion-card>
<ion-card-header>Items</ion-card-header>
<!--<ion-card-content >Your cart is empty!</ion-card-content>-->
<ion-list no-lines>
<ion-item *ngFor="let tms of cartarray;" >
<ion-avatar item-left>
<img src="">
</ion-avatar>
<h2><b>{{tms.orderitem_name}} x {{tms.orderitem_quantity}}</b></h2>
<div [ngSwitch]="product?.price_discount">
<p *ngSwitchCase="true">₹ <span st></span> <span></span></p>
<p *ngSwitchDefault>₹ <span style="text-decoration: line-through;"></span> <span></span></p>
</div>
<div>
<button primary large>
<ion-icon name="add" (click)="increaseQuantity(i)"></ion-icon>
</button>
<button primary large>
<ion-icon name="remove" (click)="decreaseQuantity(i)"></ion-icon>
</button>
</div>
</ion-item>
</ion-list>
<!--<ion-card-content ><div>Total for this order is ₹ </div></ion-card-content>-->
</ion-card>
Help me to display a value in foreach loop in ionic 3
You can try these
this.cart.cartview().then((result) => {
this.cartarray = Object.keys(result["data"]["items"]).map((key) => {
return result["data"]["items"][key];
});
})
And your html file
<div *ngFor="let tms of cartarray;">
<h2><b>{{tms.orderitem_name}} x {{tms.orderitem_quantity}}</b></h2>
</div>
i don't no ionic so thats why i'am testing with div but it's work fine.
you miss the "tms" variable name before display list of data
<ion-item *ngFor="let tms of cartarray;" >
<h2><b>{{tms.orderitem_name}} x {{tms.orderitem_quantity}}</b></h2>
</ion-item>
You should debug your array like
<ion-item *ngFor="let tms of cartarray;" >
<h2><b>{{tms | json }} x {{tms | json}}</b></h2>
</ion-item>
Thanks

Angular 7 iterate json by button click

As I mentioned in title, I want to iterate by button click over my json response. See below my json file:
{
"id": 2,
"name": "Słownictwo",
"flashcardLists": [
{
"id": 17,
"frontside": "dasfasdv",
"backside": "csdascd"
},
{
"id": 18,
"frontside": "dsadsaad",
"backside": "sdasdadad"
},
{
"id": 19,
"frontside": "dasdsadd",
"backside": "sdaddsa"
}
]
}
FlashcardHTML:
<div class="flip-container" (click)="flip()" [class.flipped]="flipped" >
<mat-card-header></mat-card-header>
<mat-card-content *ngFor="let flashcard of flashcardLists" class="flipper">
<mat-card class="front">
{{flashcard.frontside}}
</mat-card>
<mat-card class="back">
{{flashcard.backside}}
</mat-card>
</mat-card-content>
</div>
I have component where in one time I want only one "frontside" and "backside".
Next, it will be replaced by button clicked which will increase counter but I don't know how to do that. I tried something like this flashcard[0].frontside, but it was KO. Maybe someone has encountered the same problem and can help me.
For all answers thanks in advance
If I understand properly, you wanna be flipping a single card.
Something like this should do:
<mat-card-content *ngFor="let flashcard of flashcardLists" class="flipper">
<mat-card [class.front]="!flashcards[i].isFlipped"
[class.back]="flashcards[i].isFlipped"
(click)="flashcards[i].isFlipped = !flashcards[i].isFlipped "
>
{{ flashcards[i].isFlipped ? flashcard.backside : flashcard.frontside }}
</mat-card>
</mat-card-content>
Just add this map of card states to y0our component:
flashcards: { [key: string]: boolean } = {};
You don't need an *ngFor in your mat-card-content, instead bind it to a flipCard variable, which will change on button iterate click. As for the front or back, use another variable isFront which you'll update on flip button click. something like this:
component.html:
<mat-card>
<mat-card-header></mat-card-header>
<mat-card-content class="flipper">
<div class="front" *ngIf="isFront">
{{flashcard.frontside}}
</div>
<div class="back" *ngIf="!isFront">
{{flashcard.backside}}
</div>
</mat-card-content>
<mat-card-actions>
<button (click)="iterate()" class="btn-flashcard" mat-button mat-raised-button id="previous">
Następna
</button>
<button mat-button (click)="flip()" [class.flipped]="flipped">LIKE</button>
<button mat-button>SHARE</button>
</mat-card-actions>
</mat-card>
component.ts:
flashcardList: any[] // use your flashCard class instead of any
flashcard: any; // use your flashCard class instead of any
isFront = true;
ngOnInit() {
// init first card
// flashcard = first card
}
iterate() {
// logic for getting the next card
// flashcard = next card
// e.g.
let index = this.flashcardList.indexOf(this.flashcard);
this.flashcard = this.flashcardList[index + 1];
}
flip() {
this.isFront = !this.isFront;
}