I use 3 mat-select for day-month-year selection as shown on this DEMO.
I need to make the first options as null or undefined and modify that code as shown below:
allDates: number[] = [null];
dates: number[] = [null];
months: number[] = [null];
years: number[] = [null];
But I am not sure if it is a good idea or is there a proper way for mat-select. I also try to set [value]=null for the mat-select options, but in that case it does not receive the value properly. So, what is a proper way for this?
Is there a reason they need to be null? In my opinion it is more confusing to have a blank option.
Play around with the stack blitz to see how it behaves when initialized as an empty array vs when it is bound to an array with one null item. I think the UX is great when the mat-select is bound to an empty array. The mat-label resides in the select box, easy to see what type of data is in the select. Also when you click it, it doesn't show any options, because there aren't any. If you have a null, then the dropdown opens with one blank item.
I don't think there is anything wrong with the code you provided.
Edit:
You can bind the mat-select item with an object and use a display property to show the text and a value property to bind to the actual value.
Say you have an interface like this:
export interface DateSelectItem
{
value: number;
label: string;
}
let dates: DateSelectItem[] = [
{
value: -1
label: "None"
}
];
selectedDate: DateSelectItem;
in the template:
<mat-form-field>
<mat-label>Date</mat-label>
<mat-select [(ngModel)]="selectedDate">
<mat-option *ngFor="let date of dates" [value]="date">
{{date.label}}
</mat-option>
</mat-select>
</mat-form-field>
You can use just strings and convert them back and forth with their number equivalents.
Or if you use an object you can use the label property to display something other than the value.
EDIT: Modified StackBlitz
You will probably need to update the business logic on what you want the resulting date to look like if the user selects 'None' for day-of-the-month.
Updated StackBlitz
Related
On event change I'm trying to capture the value of an object that's displayed in a select drop down.
<ion-select
placeholder="Select your itinerary"
(ionChange)="handleChange($event)"
(ionCancel)="pushLog('ionCancel fired')"
(ionDismiss)="pushLog('ionDismiss fired')">
<ion-select-option *ngFor="let itinerary of myItineraries" value="{{itinerary?.itinerary}}">{{itinerary?.itinerary.destination}}</ion-select-option>
</ion-select>
There are several properties in itinerary that I need but I'm only displaying the destination. However, I need those other properties on event change.
However, when I attempt to capture the change I'm only getting [Object object].
handleChange(e) {
console.log('event', e.target);
this.pushLog('ionChange fired with value: ' + e.detail.value);
}
and this is the console.log:
ionChange fired with value: '[Object object]
After searching online I've tried using JSON.stringify(e.detail.value) simply gives me "[Object object]"
How do I get the actual values of the object's other properties?
If you want to use an object (or array) instead of a string as the value, you'd need to set it like this: [value]="itinerary?.itinerary":
<ion-select
placeholder="Select your itinerary"
(ionChange)="handleChange($event)"
(ionCancel)="pushLog('ionCancel fired')"
(ionDismiss)="pushLog('ionDismiss fired')">
<ion-select-option *ngFor="let itinerary of myItineraries" [value]="itinerary?.itinerary">
{{ itinerary?.itinerary.destination }}
</ion-select-option>
</ion-select>
Then in the component's code, you can get the selected value like this:
handleChange(e) {
console.log(e.detail.value);
}
I really don't like this solution but it works. I get the other propery values by referencing them in the html:
const test = e.detail.value.split("*");
console.log('event', test);
this.pushLog('ionChange fired with value: ' + test);
value="{{itinerary?.itinerary.destination}}, * {{itinerary?.itinerary.moreProperties}}"
The event has all of the different values in one string that I have to split.
I don't like this because it pollutes the html, and I have to use * to separate the string and I'm not 100% the order will stay the same. I have to assume the order won't change and I'll never have "*" in any of the other property fields. There's got to be a better way to do this.
I am trying to save values of two different forms in a single array and have to send them to a server using POST. Right now, I have hardcoded an array into my services.ts and I am trying to push values of an array from my .ts into that array. The problem is that when I save the form the data from that one particular form is forwarded to the array in services. I tried using the save method in submit of both the forms but That just creates 2 objects, whereas, I need One object with the other one nested inside of it. Here is the class I am using :
export interface Mod {
id : number ,
name? : string,
clauseList? : Clause
country? : string;
company? : string;
process? : string;
}
export interface Clause {
cName? : string,
cid? : number,
desc? :string,
// pc : number,
parentC? :number,
id? : number,
text? : Text
}
export interface Text {
txt? : string,
tid? : number
}
Here is the Stackblitz I cannot figure out the issue here, but in my local machine when I save the form a new object is created and displayed in the console.
Here is what I get in the console demoImage The object at [0] is the one I hardcoded and is the format I need the data in, the object at [1] is what I get on saving the forms.
Can anyone assist me with how to create a new object with the required elements in it?
Please read the readme.txt in the Stackblitz demo to get a better understanding of what I need help with
In the addFilter(...) you may simply do:
addFilter(filter: NgForm) {
this.mergedObj['filterKey'] = filter.value;
filter.reset();
console.log("filterAdded : : ", this.mergedObj)
}
Thereby, we define a key (which can be any string) to hold a value that is the current filter.value object.
I'm experiencing a problem that has me stumped. I have an ng-select. When loading records to the ngModel, it doesn't change the ng-select. The weirdest part is that on another page, the same code works.
I've tried numerous different options, even creating new arrays just to test. Also tried setTimeout to see if something is clearing the selection.
The HTML code
<label>
Add a Secondary channel
</label>
<br />
<ng-select placeholder="Select schools" items="schoolsArray" [(ngModel)]="selectedSecondSchools" [multiple]="true" name="secondSchools"
#secondSchools="ngModel">
</ng-select>
</div>
The one function in the component. The array is declared as selectedSecondSchools[] = [];
getVodEventGameSecondaryChannels(vodEventId: number, vodEventGameId: number): string[] {
let schoolIds: string[] = [];
this.vodEventService
.getVodEventGameSecondaryChannelsByGameId(vodEventId, vodEventGameId)
.subscribe((sc: IVodEventGameSecondaryChannels[]) => {
sc.forEach(gsc => {
schoolIds.push(
gsc.schoolId.toString());
});
});
this.eventGame.gameSecondaryChannelIds = schoolIds;
this.selectedSecondSchools = schoolIds;
return schoolIds;
}
When the data is returned, the returned IDs need to be selected within the ng-select and displayed.
It depends on the type of schoolsArray. In your case, I guess, schoolsArray is a list of objects, while ngModel is an array of strings. ng-select doesn't know how to map strings from ngModel to objects from items.
Please see documentation for property bindValue to inform ng-select how to bind items keys to the model. https://github.com/ng-select/ng-select
To summarize, add bindValue="id-property-name-in-items" to ng-select tag.
I am using http://www.material-ui.com/#/components/dropdown-menu and I would like to console log the primaryText of<MenuItem/> selected. How can I go about doing so?
use onChange(event: object, key: number, value: any) function.
The event object has the information about the selected item.
you can try to
console.log(event.target.textContent)
I have the following HTML:
<div class="row" ng-repeat="question in currentTemplate.questions">
<div class="col-xs-4" ng-show="editingQuestion[$index]">
<select style="width:100%;" ng-model="editingCurrentlySelectedAnswerOption[$index]"
ng-options="answerOption as answerOption.back for answerOption in answerOptions">
</select>
</div>
</div>
I am wondering how I set the value of what is shown in the select statement. When the page loads, it should already be set, because I go through a for loop to set the values of editingCurrentlySelectedAnswerOption so that each one is preselected (the [$index] is referring to the index of an ng-repeat which this is inside of. Since there are multiple selects inside the ng-repeat, I need one spot per ng-repeat in the array to keep track of each individual selection), but instead it comes up as a blank spot first. I have used ng-init, a function that is called whenever a button is pressed which unhides the above div, and a function when the page loads. I have used bindings in the DOM and console.logs to check the values. They all seem to be correct. answerOptions in the ng-options is:
var answerOptions = [
{ front: "RadioButton", back: "Multi-Choice" }
{ front: "CheckBox", back: "Multi-Answer" }
{ front: "TextBox", back: "Free Text" }
];
When I print what editingCurrentlySelectedAnswerOption[$index] is it always comes up correctly showing an object just like one of the above objects, but for some reason it is always a blank select statement when it loads. Is there something I don't know about how ng-options work with objects? Or am I doing something else wrong?
UPDATE:
I am setting the values of editingCurrentlySelectedAnswerOption this way:
this.scope.editingCurrentlySelectedAnswerOption = [];
for (var i in this.scope.currentTemplate.questions) {
if (this.scope.currentTemplate.questions.hasOwnProperty(i)) {
this.scope.editingCurrentlySelectedAnswerOption.push(this.scope.currentTemplate.questions[i].answerType);
}
}
the reason I am incrementing the amount of times there are questions in this.scope.currentTemplate is because in the html the ng-repeat repeats on the amount of questions as well. They should match up.
and this is how this.scope.currentTemplate.questions[0] is defined:
new Utilities.Question(
"Question1",
{ front: "TextBox", back: "Free Text" },
["Yes", "Maybe", "No", "I don't know"],
[50.0, 25.0, 0.0, -25.0]
)
and here is the definition of a Utilities.Question:
export class Question {
question: string;
answerType: any;
answerOptions: string[];
answerWeights: number[];
constructor(question?: string, answerType?: any, answerOptions?: string[], answerWeights?: number[]) {
this.question = question;
this.answerType = answerType;
this.answerOptions = answerOptions;
this.answerWeights = answerWeights;
}
}
Everyone was correct that ng-model/ng-options refer to the reference of an object and not the value, so even though the two object's value were correct the references were not the same and, so, the select didn't see the ng-model variable as equal to the options given. To fix this I just added a track by to the end of my ng-options and it works now. Not sure if this is the best way to do it, but it works! Thanks for everyone's help!