1
votes

I am new to knockoutjs world. I am trying to build a very simple one page UI using knockout.js. I have a observable called "sentence" in my viewModel class and I populate this value from JSON and display it to the user using data-bind in input text box.

sentence = "My first experience with knockout is {0} "

In the UI, user also has some text boxes where they can enter values.

experience = "Good"

These entered values should get replaced in numbered parameters in that sentence.

"My first experience with knockout is Good"

html:

          <select data-bind="options: titles, optionsText: 'title', optionsValue: 'backendName', value: selectedTitleId"></select>
          <input data-bind='text:text/>

js file:

   var sample = function(){
      var self = this;
      self.selectedTitleId = ko.observable();

      self.text = ko.computed(function () {
        self.displayText = test(self.selectedTitleId(),["hi"]); //This always throws  self.selectedTitleId() is not defined:
         // the real error is parameter[0] is undefined return parameters[0].replace(pattern, function (match, group) {

        console.log(self.displayText)
        //My intention is to return "{" + self.displayText + "}" to the user
        return "{" + self.selectedTitleId() + "}"; //This shows "World is great {0}"
       }); 
 }
 $.getJSON("json/queries.json", function (allData) {
    var mappedTasks = $.map(allData, function (item) {
        return new Task(item.DisplayName, item.BackendFieldName, item.QueryType)
    });
    self.titles(mappedTasks);
});

 function test() {
   return sformat.apply(this, arguments);
 }
  var sformat = (function() {
     var pattern = /\{\{|\}\}|\{(\d+)\}/g;
      return function () {
      var parameters = arguments;
       return parameters[0].replace(pattern, function (match, group) {
         var value;
           if (match === "{{")
             return "{";
           if (match === "}}")
             return "}";
           value = parameters[parseInt(group, 10) + 1];
            return value ? value.toString() : "";
       });
  };
})();

How to pass this self.selectedTitleId as a string to that test method? If i try to assign self.selectedTitleId to a var, it always complains that self.selectedTitleId() is not defined.

My requirement is pretty simple, I have this observable self.selectedTitleId which has formatted string in it and I am trying to replace the numbered parameters like {0} {1} with values. Just like how we have seen in String.format in java world.

Any help on this is deeply appreciated. I have been fighting with this for past few days.

Thanks for your time!

1
Where is self defined?Andrew Whitaker
sorry I took pieces of my code and put it together and i missed that line. I just edited a line in my question.user3773712

1 Answers

0
votes

You have a few problems:

  1. Invoking the observable before it has a value will return undefined, which is why you're getting the error. Simply initialize the observable to an empty string ('') to avoid this:

    self.selectedTitleId = ko.observable('');
    
  2. To correctly bind to an input value, you need to use data-bind="value: ..." instead. text is available on non-input elements like <p> or <div>, but since you're working with an input, you should use the value binding:

    <input type="text" data-bind="value: text" />
    
  3. Inside of your ko.computed function definition, I think just using a local variable will suffice:

    self.text = ko.computed(function () {
        // Sidenote: you don't need to pass this function an array:
        var displayText = test(self.selectedTitleId(), "hi");
    
        return "{" + displayText + "}";
    }); 
    

Example: http://jsfiddle.net/4pfhfbqe/1/


Update:

Okay so it looks like while the AJAX request is going to populate the observable arrays, selectedTitleId is undefined. I would just add a check to see if that observable is defined before processing it:

self.text = ko.computed(function () {
    if (self.selectedTitleId()) {
        var text = test(self.selectedTitleId(), "hi", "bye");
        return "{" + text + "}";
    }
    return '';
});