0

I want to turn array to select option via knockout js, I know 3 methods for this case, but none of these work perfectly with what I really want, what I want is:

  1. Set default option Choose an option
  2. get selected value
  3. set attr for options

Each method has own issue, but last method has default option and can get selected value, but can't set attr, any idea?

Method 1:

Error:

Uncaught Error: The binding 'value' cannot be used with virtual elements

Status: not working

function myfunc() {
  var self = this;
  self.estimate = ko.observableArray([]);
  self.selectedValue = ko.observable();
  
  var obj = [{
      method_title: "blah blah",
      price: "1000"
    },
    {
      method_title: "blah blah 2",
      price: "2000"
    }
  ];
  self.estimate(obj);
  self.selectedValue.subscribe(function(value) {
    alert(value);
  });
}

ko.applyBindings(new myfunc());
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<select id="method">
  <option value="0">Choose an option</option>
  <!-- ko foreach: estimate, value: selectedValue -->
  <option data-bind="text: method_title,
                       attr: { 'data-price': price, 'value': method_title },
                       text: method_title"></option>
  <!-- /ko -->
</select>

Method 2:

Status: working but I could not add default option, it looped everytime.

function myfunc() {
  var self = this;
  self.estimate = ko.observableArray([]);
  self.selectedValue = ko.observable();
  
  var obj = [{
      method_title: "blah blah",
      price: "1000"
    },
    {
      method_title: "blah blah 2",
      price: "2000"
    }
  ];
  self.estimate(obj);
  self.selectedValue.subscribe(function(value) {
    alert(value);
  });
}

ko.applyBindings(new myfunc());
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
        <select id="method" data-bind="foreach: estimate,value: selectedValue">
        <option value="0">Choose an option</option>
            <option data-bind="text: method_title,attr: {'data-price':  price, value: method_title}"></option>
        </select>

Method 3:

Status: working but I could not set attr

function myfunc() {
  var self = this;
  self.estimate = ko.observableArray([]);
  self.selectedValue = ko.observable();

  var obj = [{
      method_title: "blah blah",
      price: "1000"
    },
    {
      method_title: "blah blah 2",
      price: "2000"
    }
  ];
  self.estimate(obj);
  self.selectedValue.subscribe(function(value) {
    alert(value);
  });
}

ko.applyBindings(new myfunc());
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>

<select id="method" data-bind="value: selectedValue,options: estimate,
                       optionsText: 'method_title',
                       optionsValue: 'method_title',
                       optionsCaption: 'Choose an option'"></select>

1
  • Be aware that browsers might strip comments from inside select elements before Knockout ever sees those. IE 8 for example does that. Commented Nov 1, 2018 at 7:28

2 Answers 2

1

Your first method had the most promise and so I have corrected that. You don't need to use the value binding in the foreach loop. It has to be used in the <select>, and it works fine.

function myfunc() {
  var self = this;
  self.estimate = ko.observableArray([]);
  self.selectedValue = ko.observable();
  
  var obj = [{
      method_title: "blah blah",
      price: "1000"
    },
    {
      method_title: "blah blah 2",
      price: "2000"
    }
  ];
  self.estimate(obj);
  self.selectedValue.subscribe(function(value) {
    console.log(value);
  });
}

ko.applyBindings(new myfunc());
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<select id="method" data-bind="value: selectedValue">
  <option value="0">Choose an option</option>
  <!-- ko foreach: estimate -->
  <option data-bind="text: method_title,
                       attr: { 'data-price': price, 'value': method_title }"></option>
  <!-- /ko -->
</select>

Sign up to request clarification or add additional context in comments.

Comments

1

You just need a little bit modification with your 3rd method.

From knockout official documentation Knockout: The "options" binding you can use optionsAfterRender Parameter. I have modified your code. See if it helps

function myfunc() {
  var self = this;
  self.estimate = ko.observableArray([]);
  self.selectedValue = ko.observable();

  var obj = [{
      method_title: "blah blah",
      price: "1000",
      href: "href 1",
      title: "go to href 1"
    },
    {
      method_title: "blah blah 2",
      price: "2000",
      href: "href 2",
      title: "go to href 2"
    }
  ];
  self.setOptionAttr = function(option, item) {           
       if(item)
       {
       ko.applyBindingsToNode(option, {attr: {href:item.href,title:item.title}}, item);
       }            
    }
  self.estimate(obj);
  self.selectedValue.subscribe(function(value) {
    alert(value);
  });
}

ko.applyBindings(new myfunc());
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>

<select id="method" data-bind="value: selectedValue,options: estimate,
                       optionsText: 'method_title',
                       optionsValue: 'method_title',
                       optionsCaption: 'Choose an option',
                       optionsAfterRender: setOptionAttr"></select>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.