Javascript search for dropdown inside knockout data-bind foreach - javascript

Using knockout js
I have setup my dropdown inside a table as:
<tbody data-bind="foreach: items">
<tr>
<td id="tdName"><select class="form-control" data-bind="options: $parent.ddl, optionsText: 'firstName', value: selectedValue, optionsCaption: '--Select--', attr: { name: 'Items[' + $index() + '].Name', id: 'Items[' + $index() + '].Name'}"> </select></td>
</tr>
So it creates multiple rows of dropdowns. The above in html looks as below:
<select class="form-control" data-bind="options: $parent.ddl, optionsText: 'firstName', value: selectedValue, optionsCaption: '--Select--', attr: { name: 'Items[' + $index() + '].Name', id: 'Items[' + $index() + '].Name'}" name="Items[0].Name" id="Items[0].Name"><option value="">--Select--</option><option value="">Alex</option><option value="">Sam</option> </select>
I have a save button where I want to validate if this dropdown was selected on or not.
So I am trying to use the below code on save button click:
var selectList = $('#tdName > select');
for (var ddl of selectList ) {
if (ddl.value == '') {
ddl.className = "required text-danger form-control ddl-error"; }
}
In my console when I debug I can see the selectList as: select#Items[0].Name.form-control
So basically what I am trying to do above is loop through all the ddl and if no selection is made add the error class to it so that it is highlighted.
The issue is ddl.value is always '' so the dropdown is always highlighted.
Not sure here if I am looping though correctly here
I have my jsfiddle here as:
https://jsfiddle.net/aman1981/7wqvr854/51/
To see in action click add row, get data to populate the dropdown.
Would appreciate inputs.

You shouldn't access the DOM to check for selected values. You're already binding them to your viewmodel!
The validity check inside the Save method can access items directly:
self.save = function() {
var rows = self.items();
if (!rows.length)
alert("You cannot save an empty table");
else if (!rows.every(r => r.selectedSeperator())
alert("Some rows do not have a selected seperator");
// etc.
};

Related

Why aren't the values of the dropdowns bound?

Knockout.js is a great library to implement MVVM.
The following minimal sample binds a grid using knockout.js.
View
<div id="divDecision">
<div id="divDecisionBinding" data-bind="template: { name: 'tmplDecision' }">/div>
<script id="tmplDecision" type="text/x-jquery-tmpl">
<table id="tblDecision">
<thead>
<tr>
<th>Candidate</th>
<th>Decision</th>
</tr>
</thead>
<tbody data-bind="foreach:decisionList" id="tbList">
<tr>
<td data-bind="text: candidate"></td>
<td>
<select data-bind="attr: { id: 'cmbDecision' + ':' + $index(), name: 'cmbDecision' + ':' + $index()}, options: viewModelDecision.decisionLookup, value: 'decision', optionsText: 'decision_desc', optionsCaption: 'Please select'"></select>
</td>
</tr>
</tbody>
</table>
</script>
</div>
viewModelDecision (2 members: decisionLookup and decisionList)
decisionLookup
0 : {decision: "N", decision_desc: "No need"}
1 : {decision: "A", decision_desc: "Approved"}
2 : {decision: "R", decision_desc: "Rejected"}
decisionList
0 : {candidate: "000000001", decision: "A" }
1 : {candidate: "000000002", decision: "N" }
Script
var viewModelDecision;
//viewModelDecision gets loaded from a web service
viewModelDecision = result;
//Now the binding happens
ko.applyBindings(viewModelDecision, document.getElementById("divDecision"));
Output
000000001 Please select
000000002 Please select
Findings
The field candidate is successfully bound
The options of the dropdownlist cmbDecision:X are successfully bound
The values of the dropdownlist cmbDecision:X are not bound - the
caption "Please select" is selected by default.
Question
Why aren't the values of the dropdown list selected by default?
The value binding should be targeting an observable property of your viewmodel.
You probably meant to use the optionsValue binding to tell knockout to use the ids stored in .decision as a selection.
<select data-bind="options: viewModelDecision.decisionLookup, value: selectedDecision, optionsValue: 'decision', optionsText: 'decision_desc', optionsCaption: 'Please select'"></select>
And in your vm:
this.selectedDecision = ko.observable("A"); // Pre-select the 2nd item

knockout js selected option

I have a select tag in my html with knockout js binding.
<select class="form-control " data-bind="options: loanTimesBorrower,
optionsText: loanTimesBorrower(),
value: loanTimeBorrower,
selectedOptions: loanTimesBorrowerini,
optionsCaption: 'Choose dates'">
</select>
Instead of choose date I want to show the default value as 180, since I have a array which stores this loantime as 180 days, 360 days etc.
this is the array
self.loanTimesBorrower = ko.observableArray();
self.loanTimesBorrowerini = ko.observableArray(self.loanTimesBorrower()[0]);
and I get this array populated by a foreach loop which is getting the loantimes from db like this.
$.each(items.investTimes, function (index, item) {
self.loanTimesBorrower.push(item.Loantime);
});
So I am not sure how the default value can be put as 180 instead of choose dates
Remove
optionsCaption: 'Choose dates'
It would default to the option you provided.
You can use it like this:
<select id="selectDate" class="form-control " data-bind="options: loanTimesBorrower,
optionsText: loanTimesBorrower(),
value: loanTimeBorrower,
selectedOptions: loanTimeBorrower[0],
optionsAfterRender: $root.setDefaultDate">
</select>
And in your javascript you can do something like:
self.setDefaultDate= function (option, object) {
if (typeof object !== "undefined" && object !== null) {
if(object.value === 180) {
$("#selectDate").find(option).prop('selected', true);
}
}
};
if you show me what the object in your array looks like I can edit the answer for a better fit. But that should help you to find your way

Set "title" of selected value from dropdown after selection using knockout

I am using knockout js with ASP.NET MVC. I want to show the selected value's text on title when user hover on the selected value after selecting on the dropdown. So if bigger value hidden goes can show in title.
like: if I have three values One, Two , BiggerValuethathidden.
So now obviously if my dropdown size is not that much bigger like third value, my third value will go hidden after size defined for dropdownlist.So I want to show when set value as title on hover.
Now I have try to implement the dropdownlist bind like this:
<select class="form-control" data-bind="options: Accounts, optionsCaption: ' -- ', optionsText: function (item) { return item.AccountName }, optionsValue: function (item) { return item.Id }, value:AccountId, click: setTitle" required="required" data-parsley-required-message="Account is required" id="ddlAccounts">
To Set after so many searches , I am trying to do it like this:
<div title="" id=dvAccount">
<select class="form-control" data-bind="options: Accounts, optionsCaption: ' -- ', optionsText: function (item) { return item.AccountName }, optionsValue: function (item) { return item.Id }, value:AccountId, click: setTitle" required="required" data-parsley-required-message="Account is required" id="ddlAccounts">
</div>
click event function based on Solution:
setTip = function(c, event){
var element = event.currentTarget;
var qref = element.getAttribute('Qref');
var click_id = element.id;
return true;
}
Where am I going wrong?
Please some one help me to do this tricky trick!
You can use "attr" binding ("attr: { title: AccountId }" - you can put another (human-readable) value instead of AccountId):
<div data-bind="attr: { title: AccountId }" id=dvAccount">
<select class="form-control" data-bind="options: Accounts, optionsCaption: ' -- ', optionsText: function (item) { return item.AccountName }, optionsValue: function (item) { return item.Id }, value:AccountId, click: setTitle" required="required" data-parsley-required-message="Account is required" id="ddlAccounts">
</div>
Uffffff it is accidently or I don't know but from last 3 questions I asked question and me myself post my answer, this time again.
I found an extreme helpful solution for title of dropdown selected value:
Just use this jquery and css combination:
$('select').each(function(){
var tooltip = $(this).tooltip({
selector: 'data-toggle="tooltip"',
trigger: 'manual'
});
var selection = $(this).find('option:selected').text();
tooltip.attr('title', selection)
$('select').change(function() {
var selection = $(this).find('option:selected').text();
tooltip.attr('title', selection)
});
});
Thanks to TSV for such faster response and help me but this one is better as per my application.

Selected Dropdownlist vaue is not updating in the UI Knockout js

In my application, I am using a drop down list as shown below.
<select id="ddlcurrency" data-bind="options: $root.ddlOppCurrency, optionsText: 'CurrencyCode', optionsValue: 'CurrencyCode', optionsCaption: 'Select..', value: selectedCurrId, valueUpdate: 'change'" class="form-control"></select>
I am having a div in which the selected dropdown value has to be binded.
<div class="col-md-8 value" data-bind="text: (CurrencyID() == '' || CurrencyID() == null || CurrencyID() == undefined) ? '--' : CurrencyID">
I have created a function to bind dropdown list and a function to bind the selected value as shown below.
function ddlOppCurrency(CurrencyCode)
{
this.CurrencyCode = ko.observable(CurrencyCode);
}
function Config(CurrencyID)
{
this.selectedCurrId = ko.observable(CurrencyID);
}
Now, when I change the dropdown list, the selected value is not updating in UI. Can anyone let me know how to achieve this.
Thanks in advance.

knockout multiselect selectedOptions contains values instead of objects

I have a select with the attribute multiple. For each option in the select I want the title attribute set (which shows a tooltip). I also want to retrieve the selected options as an array of objects. I managed to get what I want except for the fact that the selected options doesnt return an array of objects but an array of valueTexts. I can't figure out how I get objects in that array.
This is the code I got so far:
HTML:
<select multiple style="width: 150px;" size=15
data-bind="foreach: options, selectedOptions: selectedOptions">
<option data-bind="text: Name, attr: { 'title': Name}"></option>
</select><br />
<button data-bind="click: showSelectedOptions">Show selection</button>
Javascript:
function Option(id, name){
var self = this;
self.Id = id;
self.Name = name;
}
function ViewModel(){
var self = this;
self.options = ko.observableArray([
new Option(0, "NormalText"),
new Option(1, "AnotherText"),
new Option(2, "WaaaaaaaaaaaaaaaayTooLongText")
]);
self.selectedOptions = ko.observableArray([]);
self.showSelectedOptions = function(){
alert(self.selectedOptions());
//what I would like to have:
//if (self.selectedOptions().length > 0)
// alert(self.selectedOptions()[0].Name);
}
}
ko.applyBindings(new ViewModel());
And the fiddle link for demonstration: http://jsfiddle.net/c63Bb/1/
What do I need to add or change so the array selectedOptions contains objects instead of strings?
Try your html like this
<select
data-bind="
options: options,
selectedOptions : selectedOptions,
optionsText: 'Name',
optionsCaption: 'Choose...'
"
size="5" multiple="true"></select>
Demo
See the console for output
EDITS :
To add attributes to option you need to use optionsAfterRender.
This is available only in version 3.1.0. I noticed your fiddle is using 3.0.0.
<select
data-bind="
options: options,
selectedOptions : selectedOptions,
optionsText: 'Name',
optionsAfterRender: $root.setTitle
"
size="5" multiple="true"></select><br />
<button data-bind="click: showSelectedOptions">Show selection</button>
And create a fnction
self.setTitle = function(option, item) {
option.title = item.Name
}
Demo
Reference
See Note 2
Similar to #MuhammadRaheel, I used optionsAfterRender:
<select data-bind="optionsAfterRender: myFunc, ...">
But I needed to use ko.applyBindingsToNode:
var self.myFunc = function(option, item) {
ko.applyBindingsToNode(option, { attr: { title: 'Tooltip!' } }, item);
}
Use options and optionsText bindings instead of foreach:
<select multiple style="width: 150px;" size=15
data-bind="options: options, optionsText: 'Name', selectedOptions: selectedOptions">
<option data-bind="text: Name, attr: { 'title': Name}"></option>
</select>
Here is demo: http://jsfiddle.net/p5E8y/

Categories

Resources