0
votes

I am a beginner with combining jQuery, Knockout and Typescript. Trying to understand why data-bind doesn't work when I try to append some code in AJAX call.

My HTML:

<div class="container">
</div>

My Typescript class (ViewModel):

export class ViewModel {
    name = ko.observable('NAME PROPERTY');

    constructor() {
        $('.container').append('<h6 data-bind="text: name"></h6>');
        this.getDataAjax();
    }

    public getDataAjax() {
        var self = this;
        $.ajax({
            type: "GET",
            url: "http://localhost:4000/GetData",
            contentType: "application/json; charset=utf-8",
            dataType: "json",
            success: function (data) {
                $('.container').append('<h6 data-bind="text: name"></h6>');
                console.log(data);
            }
        });
    }
}

Appending header with name property in constructor works fine and I can see data. However, when I append it after returning data it doesn't show at all. AJAX call works fine - cause I can see proper data in console log.

I'm working on dynamic form and need to append some HTML after ajax call. I would appreciate your help, hints, any explanation ;-) Cheers

2

2 Answers

2
votes

The idea of knockoutJS is to keep view and model separate. I would keep my header in html and then bind property

<div class="container">
<h6 data-bind="text: name"></h6>
</div>

And then just change the values of your property, it will reflect automatically.

export class ViewModel {
name = ko.observable('NAME PROPERTY');

constructor() {
    this.getDataAjax();
}

public getDataAjax() {
    var self = this;
    $.ajax({
        type: "GET",
        url: "http://localhost:4000/GetData",
        contentType: "application/json; charset=utf-8",
        dataType: "json",
        success: function (data) {
            name(data.name); //assign data.
            console.log(data);
        }
    });
}

}

BUT as you are using dynamic forms you need to applyBindings again because you appended new html element on which applyBindings never executed.

ko.applyBindings(viewModel, document.getElementById("IdProvidedToH6"));
2
votes

I mostly agree with what Amit said (and given him my upvote), but if you want dynamic forms then you could also try Knockout's html binding (when you want to bind a few lines) and template binding (when you want to show entire sections of data).

I understand that you wish to combine Knockout, jQuery and Typescript but you must understand the point of each one, and make them compliment each other. Knockout and jQuery can both manipulate data on the UI. However, Knockout's core purpose is to keep the viewModel and View in sync, while jQuery started out as a library that made selection easier.

So my recommendation is use Knockout to modify the data on your UI, and jQuery to select and capture data.

Here's two examples of adding HTML using Knockout:

<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>

<!-- Examples taken from Knockout documentation -->


HTML binding:
<div data-bind="html: details"></div>
 
<br>
Template binding: 
<div data-bind="template: { name: 'person-template', foreach: people }"></div>
 
<script type="text/html" id="person-template">
    <h4 data-bind="text: name"></h4>
    <p>Credits: <span data-bind="text: credits"></span></p>
</script>



<script type="text/javascript">
    var viewModel = {
        details: ko.observable(),
        people: ko.observableArray()
    };
    ko.applyBindings(viewModel);
    
    
    //simulate AJAX call with setTimeouts
    setTimeout(function(){
      viewModel.details("<em>For further details, view the report <a href='report.html'>here</a>.</em>");
    },1000);
    
    setTimeout(function(){
      viewModel.people([
         { name: 'Franklin', credits: 250 },
         { name: 'Mario', credits: 5800 }
     ]);
    },2000);
</script>