Knockout - Nested Observable

by Pratik Bhattachary

HTML

<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-debug.js"></script>
<input type="text" placeholder="Add Tags" data-bind="value: tagToAdd, valueUpdate: 'afterkeydown'"/>
<button data-bind="{click: addTag}">+</button>

<ul data-bind="foreach: tags">
        <li data-bind='click: $parent.selectTag'>
            <span data-bind="text: name"></span>
            <a class="tag-edit">Edit</a>
            <a class="tag-delete">Delete</a>
        </li>
</ul>

<!--Setting this div's context with selectedTag; which is a child of viewModel. So we can use name property, which although is not present in ViewModel object but is present in selectedTag-->
<div id="tagDialog" data-bind="with: selectedTag">
    Tag Name:
    <input type="text" data-bind="value: name"/>
</div>

JavaScript

$(function() {
    var data=[
        new dataItem("Pratik"),
        new dataItem("Varun"),
        new dataItem("Pradeep")
    ];   
    function dataItem (Name) {
        return {
            name: ko.observable(Name)
        };
    }
    
    //Since we are data-binding the name property of a tag we need to make sure that name is alos ko observable
    
    var viewModel = {
        tags: ko.observableArray(data),
        tagToAdd: ko.observable(""),
        selectedTag: ko.observable(""),
        addTag: function() {
            this.tags.push({name: this.tagToAdd()});
            this.tagToAdd('');
        },
        selectTag: function() {           
            viewModel.selectedTag(this);
            //alert(viewModel.selectedTag().name);
        }
    };
    
    $(document).on('click', '.tag-edit', function() {
        $('#tagDialog').dialog({
            buttons: {
                Save: function() { $(this).dialog('close'); },
                Close: function() { $(this).dialog('close'); }
            }
        });
    });
    
    $(document).on('click', '.tag-delete', function() {
        var itemToRemove = ko.dataFor(this);
        viewModel.tags.remove(itemToRemove);
    });
    
    
    ko.applyBindings(viewModel);
});