Search code examples
javascriptjsrenderjsviewsspectrumjs

how to link base type variable in JsViews custom tag


I use JsViews + spectrumjs colorpicker and i had to create custom tag like this:

$.views.tags({
    spectrum : {
        template : "<input/>",
        onAfterLink : function (tagCtx, linkCtx) {
            var tag = this;
            var props = tagCtx.props;
            var options = {
                color : tagCtx.args[0]
            };
            var linkedElem;
            if (tag._.unlinked) {
                if (!tag.linkedElem) {
                    tag.linkedElem = tag._.inline ? tag.contents("*").first() : $(linkCtx.elem);
                }
                linkedElem = tag.linkedElem;
                $.each(props, function (key, prop) {
                    var option;
                    if (key.charAt(0) === "_") {
                        key = key.slice(1);
                        options[key] = prop;
                    }
                });
                this.linkedElem.spectrum(options);
            }
        },
        onUpdate : function () {
            return false;
        },
        onDispose : function () {
            this.linkedElem.spectrum("destroy");
        }
    }
});

It works see example, but i need to dynamically update color. In spectrumjs there is event move.spectrum and sign up on him like that:

tag.spectrum = tag.linkedElem.spectrum(options);
tag.spectrum.on("move.spectrum", $.proxy(tag.moveEvent, tag));

And add handlers:

moveEvent : function (e, val) {
    // update model.color
    console.log(val.toRgbString());
    this.linkedElem.val(val.toRgbString());
},

onDispose : function () {
    this.spectrum.off("move.spectrum", $.proxy(this.moveEvent, this));
    this.spectrum.spectrum("destroy");
}

See example. So I have not tried it, I can not track changes or apply changes to model.color becose color is base type string

Update

I made an example without use custom tag of how things should work.


Solution

  • Here is an update of your example page: https://jsfiddle.net/BorisMoore/g4vs23v1/5/

    I changed the onAfterLink code as follows:

    onAfterLink : function (tagCtx, linkCtx) {
        var tag = this;
        var props = tagCtx.props;
        var options = {
            color: tagCtx.args[0]
        };
        var linkedElem;
        if (tag._.unlinked) {
            if (!tag.linkedElem) {
                tag.linkedElem = tag._.inline ? tag.contents("*").first() : $(linkCtx.elem);
            }
            linkedElem = tag.linkedElem;
            $.each(props, function (key, prop) {
                var option;
                if (key.charAt(0) === "_") {
                    key = key.slice(1);
                    options[key] = prop;
                }
            });
            tag.spectrum = linkedElem.spectrum(options);
            //tag.spectrum.on("move.spectrum", $.proxy(tag.moveEvent, tag));
            linkedElem.on("move.spectrum", $.proxy(tag.moveEvent, tag));
        } else {
            tag.linkedElem.spectrum("set", options.color);
        }
    },
    

    Specifically I corrected the binding to move.spectrum as follows

    linkedElem.on("move.spectrum", $.proxy(tag.moveEvent, tag));
    

    And when color is updated observably, such as by changing the "rgb(...)" string in the textbox, the new value needs to be set on the spectrum tag, which happens on this line:

    tag.linkedElem.spectrum("set", options.color);
    

    So now you should have two-way binding between the input binding to color and the input binding to the {{spectrum}} tag.