Angular getting value of selected author in form - html

I am using MatDialog and UntypedFormGroup. So from bookcomponent I am either adding new book or editing existing one. I am using same form to edit as well as add new book. For this particular form I am getting authors as observable for firestore and using in the mat-select and storing id of the author in book document like code below
<mat-form-field appearance="fill" *ngIf="author$ | async as authors">
<mat-label>Choose Author</mat-label>
<mat-select formControlName="authorId">
<mat-option *ngFor="let author of authors" [value]="author.id">
{{author.name}}
</mat-option>
</mat-select>
</mat-form-field>
This is working wonderfully in editing and adding new data.
Edit: I want to get selected {{author.name}} with {{author.id}} from above code. Sorry I question was ambiguous.
I am using mat-table in booklistcomponent and I want to have a column named author. I already share certain data from parent to children i.e bookcomponent<>booklistcomponent<>bookformcomponent by using #input() emitter() and MatDialog.
I tried using ngModel but it is not providing desired result. Is their any way I can use my existing code but also can get author.name value as well without any major change in editing or adding new book code. I am stuck on this one for days now please help. Thanks in advance

Related

How can I change the input received by clicking in a datalist?

I have a datalist that shows the autocompletion of some fields how can I make sure that the input is only a part of that selected field??
You can solve this problem by defining a variable of type number.
After selecting from the input, add a number to the variable and using ngIf in html or if in ts, Control the number of choices.
I assume that you have Street Names in the dropdown and that object also includes street information as well (maybe in some other variable). So you want user to search using the street information as well but in the dropdown you just want to show the user Street names? if that's the case,
you can do something like this:
<datalist>
<option>
{{streetName}} <span style="display:none">{{streetInfo}}</span>
</option>
</datalist>
This way your street information wont be shown but will filter the result on basis of stretInfo as well.
hope it helps.

Is it possible in Angular to display a value in an option but return an array to the ngModelChange?

I am trying to organize a drop down list that will display a single value to the user but will also pass back an array object upon changing the selection.
Currently I have an array called classificationresult that has 3 elements CLASSIFICATION_NAME, GROUP_ID, GROUP_NAME.
When a user selects a particular CLASSIFICATION_NAME I want to pass back the entire array result containing all 3 elements listed above.
Currently the code below works for everything EXCEPT showing the CLASSIFICATION_NAME in the drop-down box upon loading. It shows the list once you click, but it starts with a blank until it is clicked. Any way to fix this? I believe the display element is tied to [ngValue] but that is also what I am using to pass back the entire array versus just the one.
Any help would be greatly appreciated.
<p>Select Classification*</p>
<select [(ngModel)]="selectedClassification (ngModelChange)="changedClassification($event)">
<option *ngFor="let classificationresult of classificationresults" [ngValue]="classificationresult" >{{ classificationresult.CLASSIFICATION_NAME }}</option>
</select>
Summary -- I want my drop down list to always have a value shown to the user (value being the Classification Name) but when one is selected I want the entire array to pass to the changedClassification function. Also sometimes after a user selects from other drops down on this page they will also go blank, but if they are selected a second time they will populate.
If everything is working as you are expecting except the initial value being displayed, I wonder if you need a [compareWith] function. I don't know what your classificationresult model looks like, but if I had to take a guess, putting a [compareWith] function on your <select> element would fix the issue.
Here is an article explaining it a little more.
I made this Stackblitz as an example with using the [compareWith] function. In my demo I am using ReactiveForms, but the compareWith should still be the same.
For your code, it may look something like:
<p>Select Classification*</p>
<!-- add this [compareWith] -->
<select [compareWith]="myCompareFunc" [(ngModel)]="selectedClassification" (ngModelChange)="changedClassification($event)">
<option *ngFor="let classificationresult of classificationresults" [ngValue]="classificationresult" >{{ classificationresult.CLASSIFICATION_NAME }}</option>
</select>
In your .ts file:
export class YourComponent {
// all your component code..
/* compare function, change the logic to fit your needs */
myCompareFunc (classificationRes1: any, classificationRes2: any): boolean {
return classificationRes1 && classificationRes2
? classificationRes1.CLASSIFICATION_NAME === classificationRes2.CLASSIFICATION_NAME
: classificationRes1 === classificationRes2
}
}
If that doesn't fix your issue, you may need to post more of your .ts code and data models.

How to add an offset to an index in a *ngFor angular directive?

I want to display some data from a json but i can't simply add an offset to the index and show all te data from a certain offset but get
ERROR TypeError: Cannot read property 'id' of undefinedand the text in the div doesn't appear.
I have already tried to directly add a fixed number in the html file and it works (see the code below). But when it comes to use a variable "offset" (type:number) from typescript that is supposed to be updated with an input, the return type becomes undifined and the error appears. I also tried to use a method in my typescript file instead of doing the addition in the html file, and return the new index but it doesn't work and show the error. I also tried to call the method using {{addition(i,offset)}} and put the result in a variable that I use as an index but it still showing the error.
For exemple, this html file is working fine :
<ng-container *ngFor="let article of data; let i = index">
<ng-container *ngIf="i<(nbElements)">
<div (click)="checkArticle(data[(i+3)].id)">
<p class="text-center"> {{data[(i+3)][dataKey]}}</p>
</div>
</ng-container>
</ng-container>
The div reacts to my click and the text appears.
However, this html file is not working, even if the offset is set as 3 (as the html above) using an input in the parent component :
<ng-container *ngFor="let article of data; let i = index">
<ng-container *ngIf="i<(nbElements)">
<div (click)="checkArticle(data[(i+offset)].id)">
<p class="text-center"> {{data[(i+offset)][dataKey]}}</p>
</div>
</ng-container>
</ng-container>
The error appears.
The offset (type:number) is defined in my typescript file this way, and is changed by the parent component and can easily be displayed by the child component using console.log(offset):
export class AppColumnComponent implements OnInit {
#Input() offset : number ;
I expect the output to be texts showing the articles of my data json, but as I change the offset using an input like that data[(i+offset)] the result is an error, maybe it's impossible to use an other index using an other variable that a fixed number ?
Thank you for your support, it's my first post on stackoverflow i hope i did it well ! :)
If you want to make a pagination component, you should not rely solely on your HTML and some bindings.
Your component should have an "advanced" logic, in the sense that it should be able to know when it reaches the end/start of the collection (among other things).
Basically, this goes as follow :
Get the full collection (let's say 100 items)
Splice it to your item per page number (let's say 10, so results range is 0-10)
Test if items exist before the range
Test if items exist after the range
Allow/block page changing based on those variables.
This leaves you with
1 variable for the collection
1 variable (or 1 pipe) for the subset of the collection
1 variable for the items per page number
1 variable for the offset
2 booleans to disable pagination buttons.
Try working with this, and if you still have issues, then please provide a stackblitz with what you have tried !
You are accessing an index out of bounds.
data[(i+offset)] will be undefined for the last offset amount of elements in your data array so you are basically trying to do undefined.id which leads to your error.
You should change your method signature to only recieve the index as parameter and handle that case in your component.ts file

mat-select - mat-option sort values

I am new to Angular6 and I wanted to know if there is a simple way to do what I want.
I just read documentation and I did not read anything about that, is there a easy way to sort the value in the dropdown ?
<mat-form-field>
<mat-select placeholder="Code List" required [(ngModel)]="contextScheme.codeListId">
<mat-option *ngFor="let codeList of codeLists" [value]="codeList.codeListId">
{{codeList.codeListName}}
</mat-option>
</mat-select>
</mat-form-field>
Basically the value I have are the values in my DB sorted by id, I want the exact thing but sorted in desc.
Thank in advance.
Sox-.
You should do the sorting either on the database backend side, or as suggested by the Angular team in no order-by pipe it should be done inside the component.
E.g. if your have an array in the component, you could use Array.sort

<mat-select> multiple choice (formControl)

Im using Angular material's for multipe choice purpose like mentioned in their site https://material.angular.io/components/select/overview (8th example).
I also have an array of items (key and value) which are a part of the choices([key:1 value:extra cheese, key:2 value:onion])... I want them to be automatically selected (probably using formController) ... how can I do this?
plus, after the user selected/ unselectedsome options how do i get a new array back ?
thank you in advance!
you need to use ngModel
<mat-select placeholder="Toppings" [formControl]="toppings"
multiple [(ngModel)]='defaultValue'>
and define this defulatValue in your component like this, or programaticly as you wish
defaultValue = [this.toppingList[1], this.toppingList[3]]
and you can get this variable when anything changes, it will contain your selected values. Took this example from material example, all works fine for me.