Search code examples
knockout.jsknockout-validation

Get bindings from observable


How can I get data-bind string or DOM nodes which an observable is bound to? I'm using knockout.validation.js on my web page and one of my default validations (required) is getting fired. I'd like to find out which one is it being inside for example validateSync @ knockout.validation.js


Solution

  • After a while I came with something like this:

        function getPath(source, propertyName /*, value, result, noDescend */) {
            var result = arguments[3] || {};
            var valueToFind = arguments[2];
            var noDescend = arguments[4];
    
            function merge(dst, name, src) {
                var result = {};
                result[name] = src;
    
                return $.extend(true, dst, result);
            }
    
            for (var p in source) {
                var value = source[p];
                if (p == propertyName) {
                    if (!valueToFind || source[p]==valueToFind) {
                        result[p] = source[p];
                    }
                }
                else {
                    if (!noDescend && (typeof value == 'object' || typeof value == 'function')) {
                        if (ko.isObservable(value)) {
                            var r = getPath(value, propertyName, valueToFind, result[p], true);
    
                            if (Object.keys(r).length > 0) merge(result, p, r);
                        }
    
                        var r = getPath(ko.utils.unwrapObservable(value), propertyName, valueToFind, result[p]);
                        if (Object.keys(r).length > 0) merge(result, p, r);
                    }
                }
            }
    
            return result;
        }
    

    This function will give you an object which only contains properties (despite its nesting level) on name propertyName. The object being searched is source. The solution is based on the fact, that an observable has field _id when it gets bound. Here's a use case where this function is helpful.

    1. In a non-trivial form with fields bound to a non-trivial view model one of the fields breaks validation.

    2. After placing a breakpoint inside true-path of if statement in function validateSync in knockout.validation.js, check obeservable's ID by calling:

      observable._id
      
    3. Call the following command to get all the fields which breaks validation:

      getPath(ko.dataFor($('<form-selector>')[0]),'_id',<id-of-observable>)
      

    If anyone finds a better solution, please share it with me.