How to get selected menu option from a knockout.js observableArray? - select

I feel like I'm missing something very basic, but I can't get a dropdown menu to work as I expect using Knockout.js.
I have a set of objects I want to present in a menu, and I need to find the selected option and post that to the server. I can get the menu to render, but can't seem to get the value of the selected item. My view model looks like this:
function ProjectFilterItem( name, id ) {
this.Name = name;
this.Id = id;
}
function FilterViewModel() {
this.projectFilters = ko.observableArray([
new ProjectFilterItem( "foo", "1" ),
new ProjectFilterItem( "bar", "2" ),
new ProjectFilterItem( "baz", "3" )
]);
this.selectedProject = ko.observable();
}
ko.applyBindings( new FilterViewModel() );
and my view markup looks like this:
<select
id = "projectMenu"
name = "projectMenu"
data-bind = "
options: projectFilters,
optionsText: 'Name', /* I have to enquote the value or I get a JS error */
optionsValue: 'Id', /* If I put 'selectedProject here, nothing is echoed in the span below */
optionsCaption: '-- Select Project --'
"
></select>
<b>Selected Project:</b> <span data-bind="text: selectedProject"></span>
How do get the selected menu item to display in the span, and to post to the server? (I assume the observable I render in the span is the same one I'd post.) Do I need another property in the ProjectFilterItem, like this.selected = ko.observable(false); ? If so, how would I declare it as the target of the value?

You just need use with the value binding to bind the selected value:
From the options documentation:
Note: For a multi-select list, to set which of the options are
selected, or to read which of the options are selected, use the
selectedOptions binding. For a single-select list, you can also read
and write the selected option using the value binding.
In your example:
<select
id = "projectMenu"
name = "projectMenu"
data-bind = "
value: selectedProject,
options: projectFilters,
optionsText: 'Name',
optionsValue: 'Id',
optionsCaption: '-- Select Project --'
"
></select>
See Demo.

Related

Distinct Column in SelectList for dropdown list

I am retrieving distinct values from a table against only one column. when I debug ViewData in controller it has retrieved the values perfectly, but in my view it says Object is not referenced. can some one help me out.
I think the dataValueField and dataTextField are not named "TeamName" anymore after distinct is applied. how to name selected column of my choice so that below SelectList could work. thanks
Controller
ViewData["TeamNames"] = new SelectList(_context.ActivityMaps.Select(s => s.TeamName).Distinct(), "TeamName", "TeamName", model.TeamName);
View
<select asp-for="TeamName" class="form-control" asp-items="ViewBag.TeamNames"></select>
Assuming TeamName is string type.
_context.ActivityMaps.Select(s => s.TeamName).Distinct().ToList()
So the above query just return a list of string, and it doesn't have TeamName property.
Just remove the dataValueField and dataTextField.
ViewData["TeamNames"] = new SelectList(_context.ActivityMaps.Select(s => s.TeamName).Distinct().ToList(), model.TeamName);
Update:
var names = _db.ActivityMaps.Select(s => s.TeamName).Distinct().Select(n => new { TeamName = n }).ToList();
ViewData["TeamNames"] = new SelectList(names, "TeamName", "TeamName", model.TeamName);

Material-UI <Autocomplete /> different label than option value

I have a Material-UI <Autocomplete /> component I am using where you can type in someone's name and it will provide a list of people to select from. This is a pretty standard use case, however I need the selected item in the form to be different than the label.
Currently if you pick the entry labelled "John Smith", the text field will be filled with "John Smith". Instead, I want to fill the text field with that user's ID.
The data for autocomplete is an array of objects like this:
{ "name": "John Smith", "id": 123456789 }
How can I make the autocomplete component put the user ID in the text field instead of the user label?
You can customize renderOption props in Material-UI Autocomplete
Render the option, use getOptionLabel by default.
Signature: function(option: T, state: object) => ReactNode
option: The option to render.
state: The state of the component.
As for the code
getOptionLabel={option => option.name}
renderOption={(option) => <span>{option.name}</span>}
Refer to the demo in an official document
If you just want to display name in Textfield, You could try this
getOptionLabel={option => option.id}
renderOption={option => <>{option.name}</>}
If you want to display name in TextField and OptionLabel but want to get id as value of TextField in order to store id after form submission.
You could try this
getOptionLabel={(option) => option.name}
renderOption={(option) => (
<>
{option.name} ({option.surname})
</>
)}
onChange={(event, newValue) => {
setValue(newValue);
setCustomValue(newValue.id);
}}
using onChange event you could select any field of the option you want to get as value.In this example I stored id of the option in the state.
Complete working example is here https://codesandbox.io/s/material-demo-forked-wlzr8?file=/demo.js:804-1084

UI5 - how to dynamically bind data to a Select in Table, depending on another combobox?

I have a classic situation - a table with two comboboxes (or, to be exact, sap.m.Select controls) and after select in the first one, I would like to have the values in the second one updated. This is my model, basically, the first combobox should contain the list of available states and once some is selected, the second sap.m.Select control should be populated by relevant cities
{
countries: [
{ country: 'France', cities: ['Paris', 'Marseille', 'Lyon']},
{ country: 'Germany', cities: ['Berlin', 'Bonn']}
]
}
The problem is that I dont know how to do it. I am able to get the id of the updated row using something like this.
onCountryChange: function (oEvent) {
const selectedItem = oEvent.getParameter("selectedItem");
var path = selectedItem.getBindingContext().getPath();
bindComboBox(path); // this should rebind the data, but not written yet
}
I know now I should rebind the data in the correct combobox, however, I don't know how to affect only that single combobox on the correct row and how to update it. Could someone advise me how to do it? The whole table is defined in the .xml view, can I do it also with a formatter or inline expression or is this scenario too difficult for that?
Thank you
You can use the bindAggregation method (from the ManagedObject) class to rebind the combo boxes' items.
onCountryChange: function (oEvent) {
const selectedItem = oEvent.getParameter("selectedItem");
var path = selectedItem.getBindingContext().getPath();
this.byId("combo2").bindAggregation("items", {
path: path + "/cities",
template: new sap.ui.core.Item({
key: "{}",
text: "{}"
})
});
}
Note: Replacing "combo2" with the id of your 2nd combo box/select control.
Edit: To get the correct combo box (assuming you have multiple created on a table, use the ID of the first combo box (oEvent.getSource().getId()) to generate the ID of the 2nd combo box. Without knowing more of the structure of the table (and how it's created) I can't offer more.

vue - select option change triggers vuex mutation error

I'm using vue2.
I want to get select option object in v-for
HTML:
<select
class="custom-select"
#change="onPlanSelected($event)"
v-model="selectedPlan.objectId">
<option
v-for="plan in plans"
:key="plan.objectId"
:value="plan.objectId">
{{ plan.title }}
</option>
</select>
JS:
data () {
return {
selectedPlan: {}
}
}
onPlanSelected (event) {
this.selectedPlan = this.plans.find(plan => {
return plan.objectId === event.target.value
})
}
when I change the select option, I get the error:
As you can see selectedPlan is data not vuex.
Btw, how to get an object from a select v-for option
Thanks
First of all I don't see the need of using #change in your case. v-model should be sufficient for handling the selected option.
Here is a sample fiddle: https://jsfiddle.net/z11fe07p/567/
As long as you have the whole object as :value and v-model as well you always have the selected option along with it's id.

How to allow editing of cells within SAPUI5 Table

Can you please show me how to allow editing of cells within SAPUI5 table? I am using JSON model.
look at this examples in the SDK Table.html, both of the examples show how to set a json model, set the json model as a data source of a table control, how to bind rows of the json to rows of the table, and how to bind the values to cells, once you change the cells values the new value will be reflect in the model
var employeeData = [
{lastName: "Dente", name: "Al"},
{lastName: "Friese", name: "Andy"},
{lastName: "Mann", name: "Anita"},
{lastName: "Schutt", name: "Doris}
];
//create the JSON model and set your data
var oModel = new sap.ui.model.json.JSONModel();
oModel.setData({ Employees: employeeData });
//create table
var oTable = new sap.ui.table.Table();
//add a column for lastname and bind the value to an editable textview
oTable.addColumn(new sap.ui.table.Column({
label: new sap.ui.commons.Label({text: "Last Name"}),
template: new sap.ui.commons.TextView().bindProperty("text", "lastName"),
});
//add a column for name and bind the value to an editable textview
oTable.addColumn(new sap.ui.table.Column({
label: new sap.ui.commons.Label({text: "First Name"}),
template: new sap.ui.commons.TextField().bindProperty("value", "name"),
}));
oTable.setModel(oModel);
oTable.bindRows("/Employees);
First your table template objects have to be editable. For a textfield either use the setEditable(true), bindProperty('editable',true) or directly in the construtor new TextField({editalbe:true}).
If it is editable ensure you have switched on two way binding in your model. For JSON models this is the default I think. Also ensure, that there are no formatters involved, because these will destroy two way binding.
The you can check in your debugger, if the changes on the UI are transfered to the model. In general this works fine and from this point it is up to you what to do with the model (send it to some oData save service).
I had the same issue with a table that had to be editable when the value was zero and non-editable when it was greater than zero.
Value1 is my dinamic value.
Value2 is zero
<Input type="Number" editable="{parts:[{path : 'Value1'}, {path : 'Value2'}], formatter:'sap.ui.app.model.formatter.CantEditable'}"/>
Inside the formatter i defined a function called CantEditable like this.
jQuery.sap.declare("sap.ui.app.model.formatter");
sap.ui.app.model.formatter =
{
function1: (Value1, Value2)
{
//If value 1 > Value 2 return editable
if (Value1>Value2)
{
return false;
}
else
{
return true;
}
};
Since its binded to the value of these two variables. Whenever my value one changes, the editable function will check if it meets the requeriments of the function. Then it will change the value of the editable property.
My sap.m.Table demo here:
http://plnkr.co/edit/qifky6plPEzFtlpyV2vb?p=preview
I am using data-sap-ui-theme="sap_belize", you can change it to sap_bluecrystal.
The basic idea is using editable property of sap.m.Input, and enabled property of sap.m.Select.
I opened an issue of ui5 to discuss this problem: https://github.com/SAP/openui5/issues/1646