Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

Add optionsTitle data binding for setting the title attribute of options. #196

Closed
wants to merge 1 commit into from

3 participants

@amonat

Add optionsTitle data binding for setting the title attribute of options.

This commit adds a new data binding called optionsTitle that sets the 'title' HTML attribute of an option that's created by an options data binding. It doesn't set the title attribute if the result of evaluating the binding is the empty string.

Another possible implementation for this would be to instead make an optionsAttr binding that works like the attr binding (http://knockoutjs.com/documentation/attr-binding.html) but applies to the created options rather than the , which would have the advantage of being more flexible.

@worldspawn

+1 for the "other possible implementation"

@amonat

I've opened a new pull request with the "other possible implementation" (#252) which has optionsAttr rather than optionsTitle, as I offered and worldspawn +1'd.

@mbest
Collaborator

Closing in favor of #382.

@mbest mbest closed this
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
This page is out of date. Refresh to see the latest.
Showing with 24 additions and 7 deletions.
  1. +11 −7 spec/defaultBindingsBehaviors.js
  2. +13 −0 src/binding/defaultBindings.js
View
18 spec/defaultBindingsBehaviors.js
@@ -362,28 +362,32 @@ describe('Binding: Options', {
value_of(displayedOptions).should_be(["A", "B", "C"]);
},
- 'Should accept optionsText and optionsValue params to display subproperties of the model values': function() {
+ 'Should accept optionsText, optionsValue and optionsTitle params to display subproperties of the model values': function() {
var modelValues = new ko.observableArray([
- { name: 'bob', id: ko.observable(6) }, // Note that subproperties can be observable
- { name: ko.observable('frank'), id: 13 }
+ { name: 'bob', id: ko.observable(6), job: 'manager' }, // Note that subproperties can be observable
+ { name: ko.observable('frank'), id: 13, job: ko.observable('coder & tester') }
]);
- testNode.innerHTML = "<select data-bind='options:myValues, optionsText: \"name\", optionsValue: \"id\"'><option>should be deleted</option></select>";
+ testNode.innerHTML = "<select data-bind='options:myValues, optionsText: \"name\", optionsValue: \"id\", optionsTitle: \"job\"'><option>should be deleted</option></select>";
ko.applyBindings({ myValues: modelValues }, testNode);
var displayedText = ko.utils.arrayMap(testNode.childNodes[0].childNodes, function (node) { return node.innerHTML; });
+ var displayedTitle = ko.utils.arrayMap(testNode.childNodes[0].childNodes, function (node) { return node.title; });
var displayedValues = ko.utils.arrayMap(testNode.childNodes[0].childNodes, function (node) { return node.value; });
value_of(displayedText).should_be(["bob", "frank"]);
+ value_of(displayedTitle).should_be(["manager", "coder & tester"]);
value_of(displayedValues).should_be([6, 13]);
},
- 'Should accept function in optionsText param to display subproperties of the model values': function() {
+ 'Should accept function in optionsText and optionsTitle params to display subproperties of the model values': function() {
var modelValues = new ko.observableArray([
{ name: 'bob', job: 'manager' },
{ name: 'frank', job: 'coder & tester' }
]);
- testNode.innerHTML = "<select data-bind='options:myValues, optionsText: function (v) { return v[\"name\"] + \" (\" + v[\"job\"] + \")\"; }, optionsValue: \"id\"'><option>should be deleted</option></select>";
+ testNode.innerHTML = "<select data-bind='options:myValues, optionsText: function (v) { return v[\"name\"] + \" (\" + v[\"job\"] + \")\"; }, optionsTitle: function (v) { return v[\"name\"] + \" (title: \" + v[\"job\"] + \")\"; }, optionsValue: \"id\"'><option>should be deleted</option></select>";
ko.applyBindings({ myValues: modelValues }, testNode);
var displayedText = ko.utils.arrayMap(testNode.childNodes[0].childNodes, function (node) { return node.innerText || node.textContent; });
+ var displayedTitle = ko.utils.arrayMap(testNode.childNodes[0].childNodes, function (node) { return node.title; });
value_of(displayedText).should_be(["bob (manager)", "frank (coder & tester)"]);
+ value_of(displayedTitle).should_be(["bob (title: manager)", "frank (title: coder & tester)"]);
},
'Should update the SELECT node\'s options if the model changes': function () {
@@ -1371,4 +1375,4 @@ describe('Binding: Foreach', {
value_of(testNode).should_contain_html('<ul><li>header item</li><!-- ko foreach: someitems --><li data-bind="text: $data">alpha<li data-bind="text: $data">beta</li><!-- /ko --></ul>');
}
}
-});
+});
View
13 src/binding/defaultBindings.js
@@ -220,6 +220,19 @@ ko.bindingHandlers['options'] = {
typeof option.innerText == "string" ? option.innerText = optionText
: option.textContent = optionText;
+ // Apply a title to the option element if specified
+ var optionsTitleValue = allBindings['optionsTitle'];
+ if (typeof optionsTitleValue == "function")
+ optionTitle = optionsTitleValue(value[i]); // Given a function; run it against the data value
+ else if (typeof optionsTitleValue == "string")
+ optionTitle = value[i][optionsTitleValue]; // Given a string; treat it as a property name on the data value
+ else
+ optionTitle = ""; // Given no optionsTitle arg; use the empty string
+ optionTitle = ko.utils.unwrapObservable(optionTitle).toString();
+ if (optionTitle !== "") {
+ option.title = optionTitle;
+ }
+
element.appendChild(option);
}
Something went wrong with that request. Please try again.