rlcrews
rlcrews

Reputation: 3562

how to set an observable value based upon the selected/clicked element

I have a sample I am trying to detect the text value of a selected element and have it populated in a popup window. I know how to do this using jQuery but I don't want to bring Ui awareness into the viewmodel. I know i am missing something simple but can someone explain what I need to do to bind the text value from an element selected in the UI and have it bound to another observable within Knockout.

Full working JsFiddle

Minus the CSS here is the html and JS that I have hooked up thus far

<ul data-bind="foreach: items">
    <li class="divContainer"> <span title="filename" class="tbox" data-bind="text: name, click: $root.openControl "></span>
 <span title="description" class="tbox" data-bind="text: description"></span>

    </li>
</ul>
<div id="nameDiv" class="nameContainer"> <span class="smallTitle"></span>

    <input type="textbox" class="mytextbox" data-bind="value: currentField" />
    <input type="button" id="SaveChange" class="editbtn" value="&#x2714;" />
    <input type="button" id="CancelChange" class="editbtn" value="&#x2716;" />
</div>

JS

var Item = function (name, description) {
    this.name = ko.observable(name);
    this.description = ko.observable(description);
}

    function myViewModel() {
        var self = this;
        //sample list of items
        self.items = ko.observableArray([
        new Item('item 1', ' item 1 Description'),
        new Item('item 2', 'item 2 Description'),
        new Item('item 3', 'Report3 Description'),
        new Item('item 4', 'Report4 Description')]);

        //observable fields
        self.currentField = ko.observable("");

        //bind current item text to field
        self.openControl = function () {
            self.currentField($(this)); ///Here I need to pick up the text of the item that was clicked on
        };
    };

ko.applyBindings(new myViewModel());

function positionDiv(x_pos, y_pos) {

    var d = document.getElementById('nameDiv');
    d.style.display = 'none';
    d.style.position = 'absolute';
    d.style.left = x_pos + 'px';
    d.style.top = y_pos + 'px';
    $('#nameDiv').fadeIn('slow');
}
$('.tbox').click(function () {
    var myText = $(this);
    var t = $(this).attr('title');
    if (t === 'filename') {
        $('.smallTitle').text('Enter new filename');
    } else {
        $('.smallTitle').text('Enter new description');
    }
    displayEditBox(myText);
});


function displayEditBox(myText) {

    //determine middle of span element
    var offset = myText.offset();
    var width = myText.width();
    var height = myText.height();
    var centerX = offset.left + width + 5;
    var centerY = offset.top - 10;

    positionDiv(centerX, centerY);
}

$('#CancelChange').click(function () {
    $('#nameDiv').fadeOut('fast');
    clearField($('.mytextbox'));
});

function clearField(field_name) {
    field_name.val('');
}

Thanks in advance,

Upvotes: 0

Views: 482

Answers (1)

Timothy Shields
Timothy Shields

Reputation: 79441

Change your definition of the openControl function to take a parameter:

self.openControl = function (item) {
    self.currentField(item.description());
};

This should be the item (an element of the items array) that the click was applied to, because at the location where the click binding is made, the data context is the body of the foreach: items binding.

Upvotes: 3

Related Questions