I am unable to get select options to update dynamically with Angular2 bindings. How do you update the contents of the select dynamically?
Plnkr explaining my issue. Notice the select options never update to the new array i set.
Because when you are reassinging options value you have to point to options of current by using this before options.
handleChange(event) {
console.log(event.target.value);
//this to indicate options from current class
this.options = [{id: 0, name:"First"}, {id: 1, name:"Second"}, {id: 2, name:"Third"}];
this.selected1 = this.options.filter((option) => {
return option.id == event.target.value;
})[0];
}
Demo Plunkr
Related
I am working on an Earth Engine application where I have 2 widgets of type ui.Select that are dependent on each other (bidirectionally dependent). That is, when I make a change in one of them, it changes the list in the other and vice versa.
The behavor is correct, except that when I want to reselect the option that was before the change, it does not work. Due to the items generator script that populate the widgets is allways sure that the previous selection is in the new (modified) items list.
Here are the two widgets implementations
var select_date_init = ui.Select({
items: Object.keys(dates_init),
onChange:function(key) {
var selected_end = select_date_end.getValue();
var selected_init_end_date = dates_init[key][1];
var new_list = Object.keys(get_dates_list(selected_init_end_date,''));
select_date_end.items().reset(new_list);
//select_date_end.items = new_list
if(selected_end !== null){
select_date_end.setValue(selected_end,false)
}else{
select_date_end.setValue(null,false)
}
},
placeholder: 'Seleccionar semestre 1...'
});
var select_date_end = ui.Select({
items: Object.keys(dates_end),
onChange: function(key) {
var selected_init = select_date_init.getValue();
var selected_end_init_date = dates_init[key][0];
var new_list = Object.keys(get_dates_list(system_date_init,selected_end_init_date));
select_date_init.items().reset(new_list);
//select_date_init.items = new_list;
if(selected_init !== null){
select_date_init.setValue(selected_init,false)
}else{
select_date_init.setValue(null,false)
}
},
placeholder: 'Seleccionar semestre 2...'
});
The problem seems to be on the setValue() part of the script. The items of the two widgets are correctly changed, but it allways show the 'Seleccionar semestre 1...' or 'Seleccionar semestre 2...' default text after the change action.
The action I need is:
First step:
Select from 1 -> this changes the list on 2 (originally empty so no pre-selection needed)
Second step:
Select from 2 -> this changes the list on 1 (but keep the selected option in 1)
If the user wants:
Change selection from 1 (or 2) -> update the other list -> keep pre-selected options
Here is the link to the full working script https://code.earthengine.google.com/b251b24ffbc37775e4e5eede8dcbd11f
The onChange function of your button #2 is resetting your button #1 every time. You only need to uncomment lines 209-216 of your code, so the onChange function of your variable var select_date_end looks like this:
var select_date_end = ui.Select({
items: Object.keys(dates_end),
onChange: function(key) {
var selected_init = select_date_init.getValue();
var selected_end_init_date = dates_init[key][0];
var new_list = Object.keys(get_dates_list(system_date_init,selected_end_init_date));
},
placeholder: 'Seleccionar semestre 2...'
});
See code: https://code.earthengine.google.com/9e2d4f13e9bfa57e1df3673a6d82684e
I have multiple <mat-button-toggle> elements generated in my app and I want always only one selected. The problem that I now have is, how to get the component reference to the last selected toggle-button when another toggle button is clicked.
I really searched quite a while but couldn't understand how to do it.
component.html
<mat-button-toggle (click)="onKeywordSelect($event)" *ngFor="let keyword of keywords" [id]="keyword.id" [attr.id]="keyword.id" [value]="keyword.id" class="keyword">
<div class="text">{{ keyword.name }}</div>
</mat-button-toggle>
component.ts
// imports and #Component
export class NavbarComponent implements OnInit {
keywords = [new Keyword('name1'), new Keyword('name2')]; // sample data
$selectedKeyword: $ | any; // I've imported JQuery
onKeywordSelect(event: any) {
// This element depends on where you mouse was positioned when clicking
// Most often not the <mat-button-toggle> but some child element
const target = event.target;
// To get to the <mat-button-toggle> component that was clicked
const matButton = $(target).closest('mat-button-toggle');
if (this.$selectedKeyword !== undefined) {
// At the start there is no selected keyword
// TODO: Set the 'checked' property of the cur selected keyword to false
}
this.$selectedKeyword = $matButton;
}
}
I tried it with #ViewChild() but because the id of the selected keyword changes when the user selects one I don't know how to keep track of the selected component reference.
Edit
Forgot to mention: Yes I'm aware of mat-button-toggle-group but I don't want to use it because of some styling. Is there no other way to solve this?
Edit: Updated my ans as your requirement is not to use mat-button-toggle-group:
You can use checked property and set current and last selected value on change event like this:
component.html:
<mat-button-toggle
*ngFor="let keyword of keywords"
value="{{keyword.id}}"
[id]="keyword.id"
[attr.id]="keyword.id"
(change)="this.onChange(keyword.id)"
[checked]="this.currValue === keyword.id">
{{keyword.name}}
</mat-button-toggle>
<div class="example-selected-value">
Last Selected value: {{this.lastValue}}
</div>
<div class="example-selected-value">
Current Selected value: {{this.currValue}}
</div>
component.ts:
keywords: any = [
{id: 1, name: "name1"},
{id: 2, name: "name2"},
{id: 3, name: "name3"},
]
lastValue: string = "";
currValue: string = "";
onChange = (value) => {
this.lastValue = this.currValue;
this.currValue = value;
}
Check Demo Here.
Add mat-button-toggle-group to select only one button and get value of group to get last selected button
see: https://stackblitz.com/angular/yrqebgjbxao?file=app%2Fbutton-toggle-exclusive-example.ts
I want an auto increment column in my Kendo Grid. This field isn't server side auto increment, because I want the user to see the value and be able to change it.
My current solution is to add a click attribute to Create button and loop over rows to find the highest value and increment it.
But how can I insert this value inside the newly created row? Click event happens before the new row is created.
So there is two possible solution:
Have a variable as default value and update it in my JS code.
Access the newly created row somehow, and update the value.
This is my JS code:
function createClick(id) {
var grid = $("#" + id).data('kendoGrid');
var highestRadif = 0;
grid.tbody.find('>tr').each(function () {
var dataItem = grid.dataItem(this);
var radif = dataItem.SRadifReqR;
highestRadif = highestRadif < radif ? radif : highestRadif;
})
alert(++highestRadif);
}
You can use Grid's edit event to add your new generatedId value to new Grid's model.
This is some explanation from their documentation:
Edit
fired when the user edits or creates a data item.
e.container jQuery, jQuery object of the edit container element, which wraps the editing UI.
e.model kendo.data.Model, The data item which is going to be edited. Use its isNew method to check if the data item is new
(created) or not (edited).
e.sender kendo.ui.Grid, The widget instance which fired the event.
I suppose your click have something like this
//generate id code
vm.newId = ++highestRadif; // we need to store generated Id
grid.addRow();
then on edit event
edit: function(e) {
var model = e.model; // access edited/newly added model
// model is observable object, use set method to trigger change event
model.set("id", vm.newId);
}
Note: Your schema model's field must set property editable: true, due to enable us to change model field value using set method. Also if your field schema have validation required, you need to remove it.
model: {
id: "ProductID",
fields: {
ProductID: { editable: true, nullable: true },
}
}
Sample
I was able to put a function in the datasource schema for this.
schema: {
model: {
id: "id",
fields: {
currencyType: { defaultValue: getDefaultCurrency },
invoiceDate: { type: "date" }
}
}
}
function getDefaultCurrency() {
return _.find(vm.currencyTypes, { id: vm.currencyId });
};
I have a Kendo DropDownList (name=Function) that contains 3 options. When one option is selected, it triggers an ajax call to get data to populate a different DropDownList (name=Parents). This works as-expected. However, if the user then changes the original DropDownList "Function" back to a different selection, I need to clear/reset (remove all options) and disable the "Parents" DropDownList.
function LoadKendoDropdownContents(dropdownBoxId, data) {
var dropdownBox = $("#" + dropdownBoxId).data("kendoDropDownList");
if (data === "" || data === null || $.isEmptyObject(data)) {
var dataSource = [];
}
else {
var dataSource = data;
}
dropdownBox.setDataSource(dataSource);
}
It's really the "var dataSource = []" that is giving me problems. It's like the "Parents" DropDownList isn't refreshing/rebinding when that is applied. All of the options except the one that was selected get removed, but how do I remove the one that was previously selected? I want it to be "empty" again.
Thank you.
---- Solution I used ----
function LoadKendoDropdownContents(dropdownBoxId, data) {
var dropdownBox = $("#" + dropdownBoxId).data("kendoDropDownList");
if (data === "" || data === null || $.isEmptyObject(data)) {
var dataSource = new kendo.data.DataSource({
data: []
});
dropdownBox.text(" --- ");
dropdownBox.value(-1);
}
else {
var dataSource = new kendo.data.DataSource({
data: data
});
dropdownBox.text("[Select]");
dropdownBox.value(-1);
}
dropdownBox.setDataSource(dataSource);
}
It might be easier to use the cascading dropdown feature.
When you change the dataSource, it removes the dropdown items, but you also need to clear the selected text and disable the box, by calling:
dropdownBox.setDataSource(dataSource);
dropdownBox.text('');
dropdownBox.enable(false);
If you have defined a data source for both the parent and child drop down then you could use the cascadeFrom('parent') method in the child and set a value that you can identify as null or clear.
I'm currently studying knockoutjs and I was just following the tutorial on list and collection on the official website of knockoutjs, currently what I have is a dropdown that lists the items I have and then adjacent to it is a text that displays the text(price), now what I want to happen is that the text displayed should change based from the selected item of the dropdown.
Here is a jsfiddle of my code: http://jsfiddle.net/UQskS/
Also, if you notice something wrong with my code aside from what I mention above please do advise me, for best practice or for correction.
// Class to represent a row in the seat reservations grid
function SeatReservation(name, initialMeal) {
//var self = this;
//self.name = ko.observable(name);
this.name = name;
this.meal = ko.observable(initialMeal);
this.formattedPrice = ko.computed(function () {
var price = this.meal().price;
return price ? "$" + price.toFixed(2) : "None";
}, this);
}
function ReservationsViewModel(name, meal) {
//var self = this;
// Non-editable catalog data - would come from the server
this.availableMeals = [
{ mealId: 1, mealName: "Standard (sandwich)", price: 47.55 },
{ mealId: 2, mealName: "Premium (lobster)", price: 34.95 },
{ mealId: 3, mealName: "Ultimate (whole zebra)", price: 290.123 }
];
//editable data
this.seats = ko.observableArray([
new SeatReservation("Randel", this.availableMeals[2]),
new SeatReservation("Knockout", this.availableMeals[1])
]);
//operations
this.addSeat = function () {
this.seats.push(new SeatReservation("", this.availableMeals[0]));
};
this.removeSeat = function (seat) {
this.seats.remove(seat);
;}
}
ko.applyBindings(new ReservationsViewModel());
Sir/Ma'am, your answers would be of great help. Thank you++
The only thing you really need to change from how you currently have it coded is the options binding parameters.
You are using optionsValue and then trying to update the id on the meal property. This is just going to overwrite the mealId property without changing the object it is referring to.
This jsFiddle demonstrates what is going on. Notice that you have to click the refresh link in order to force the UI to update since mealId is not an observable.
To fix this, you just need to bind the value directly to the selected object instead.
<select data-bind="
options: $root.availableMeals,
value: meal,
optionsText: 'mealName',
optionsCaption: 'Choose...'">
</select>
Here is the updated (and working) fiddle: http://jsfiddle.net/jwcarroll/nrHcs
Update:
If you want to use the mealId because you will be pulling these values from the database, then at some point you will have to do a lookup to get the other values. Either you pay the price up front, or when you are saving.
Here is an updated fiddle that shows one way of how you might accomplish this.
http://jsfiddle.net/jwcarroll/YAMS5/