3.0 beta 2

Active.Format Object's access to data in other columns of the model

I was trying to write the Anchor Format object I saw alluded to on one of the other posts. I tried doing this with a Template, but it seemed that the template was only initialized once, and didn't allow for dynamic rendering of the link, but this was probably my ignorance of the codebase and very limited knowledge of javascript's runtime rules.

The following works for static links and would also allow the raw data value to be part of the hyper link but is fairly limited in what it can do. I want to make it possible for any columns data value to be part of the href attribute.

Is there a standard way to reference the model from a Format Object?
What is the property to get the models current row?

I want to be able to resolve properties in a Format Object using other columns from the model's current row however, I am not sure how to reference the other columns data values, or reference the current row

I was thinking of using a syntax such as
var myAnchorFormat = new Active.Formats.Anchor();
myAnchorFormat.setLink( "http://www.google.com?q={1}" );

Where "{1}" would be resulved to the data value from model.getData(currentRow, 1);

I could set the model into the Anchor Format Object, but then I still wouldn't know the current row. I thought I had seen this in the forum somewhere, but I've been looking for a few days, and haven't been able to find it.



Here is what I have so far.

Active.Formats.Anchor = Active.Formats.String.subclass();

Active.Formats.Anchor.create = function(){

    var obj = this.prototype;

    var _link = null;

    obj.setLink = function( l ) {
        _link = l;
    }

    obj.getLink = function(src,data) {
        var l = _link;
        if (typeof(l)=="function") {
            l = l.call(this,src,data);
        }
        return l;
    }

    obj.dataToText = function(data){
        var html = new Active.System.HTML();
        html.setTag("a");
        html.setContent(data);
        if (_link) {
            html.setAttribute( "href", obj.getLink(this,data) );
            }
        return html;
    };

    obj.dataToValue = function( data ) {
        return data;
    }

        // plus some regex code to extract and replace
        // column references with their values from the result of
        // _link

};

Active.Formats.Anchor.create();
gbegley
March 29,
Here is the regex search and replace code. I am sure there is a cleaner way to do this...
var resolveFromModel = function( raw ) {
        var str = raw;
        var result = str;
        // define search pattern
        var pattern = /\{(\d+)\}/g;
        var results = pattern.exec( str );
        while (results) {
            str = str.replace( results[0], getColumnValue( results[1] ) );
            results = pattern.exec( str );
        }
        return str;
    }

/**
 * this function still needs to be written
 */
    var getColumnValue = function( colIndex ) {
        return "cv_"+colIndex;
    }



// then 
...
var anc0 = new Active.Formats.Anchor();

var model = new Active.XML.Table;
model.setFormat( anc0, 0 );
anc0.setLink( function( src, data ){
    return "http://www.google.com?q={1}&bar={2}";
} );
...
gbegley
March 29,
I don't know yet what is the proper solution for your case. Formatting object seems to be a natural solution, but it is designed to receive only one input and produce only one output, so it does not work with multiple values.

Here is probably the quick way to get the result you are looking for:
//	create xml data model
var table = new Active.XML.Table;

//	save the default getText method
var getText = table.getText;

//	define new custom getText method
table.getText = function(i, j){
    if (j != 4) {
        return getText.call(this, i, j);
    }
    else {
        var link = "<a href='{2}'>{1}</a>";
        var param1 = getText.call(this, i, 1);
        var param2 = getText.call(this, i, 2);
        return link.replace("{1}", param1).replace("{2}", param2);
    }
}

//	define new custom getValue method
table.getValue = function(i, j){

// do something similar for getValue method, which defines sorting
}
...

var obj = new Active.Controls.Grid;
obj.setModel("data", table);

//   hide columns 1 and 2
obj.setProperty("column/values", [0,3,4]);

Alex (ActiveWidgets)
March 29,
It took me awhile to get this worked out, but I've finally got it.

Since a column template has a row template as it's $owner property, and the row template can be used to access values from the other columns, then as long as the anchor is used as column template, then the columnTemplate.$owner property can be used to access the other columns values.

Here is the code to solve the problem mentioned above.


Active.Templates.Anchor = Active.System.Template.subclass();

Active.Templates.Anchor.create = function(){

/****************************************************************
    Anchor Cell template. If this Template is a child of an 
    Active.Templates.Row Object, it will automatically
    convert {colIndex} (eg {0},{1}, etc) to the values from the
    respective columns on the row. For example, if column 0 
    contains the value 1234 then {0} will be replaced by 1234 
    in the href hyperlink.
*****************************************************************/

    var obj = this.prototype;
    var _super = this.superclass.prototype;

//	------------------------------------------------------------
    obj.setClass("templates", "item");
    obj.setClass("box", "anchor");

//	------------------------------------------------------------

    var anchor = new Active.System.HTML;
    anchor.setTag("a");
    anchor.setAttribute("href", function() {
        var rawLink = this.getHref();
        var link = this.processLink( rawLink );
        return link;
    });

//	------------------------------------------------------------

    anchor.setClass("item", "anchor");
    anchor.setClass("anchor", function(){return this.getItemProperty("index")});

    obj.setContent("anchor", anchor);
    obj.setContent("anchor/text", function(){return this.getItemProperty("text")});

    /****************************************************************
        Allows specification of custom anchor href attribute
    *****************************************************************/
    var href = "javascript:void();";
    obj.setHref = function( link ) { href = link; }
    obj.getHref = function() {
        var a = href;
        if (typeof(a)=='function') a = a.call(this);
        return a;
    }


    /****************************************************************
        Performs search and replace on the regular expression /\{(\d+)\}/g;
        (eg {0} -> 0 ) and replaces the value with it's referenced column's
        text value. 

        todo: how do you get the unformatted column value???
    *****************************************************************/
    obj.processLink = function( link ) {
        if (this.$owner) {
            var row = this.$owner;
            var pattern = /\{(\d+)\}/g;
            var str = link;
            var results = pattern.exec( str );
            while (results) {
                var colIndex = results[1];
                var colValue = row.getDataProperty( "text", colIndex );
                str = str.replace( results[0], colValue ? colValue : colIndex );
                results = pattern.exec( str );
            }
            link = str;
        }
        return link;
    }

};

Active.Templates.Anchor.create();
gbegley
April 16,
BTW, Obviously I ended up going with the Active.System.Template over the Active.System.Format Object as a base. This provided for a much cleaner implementation.

I pretty new to javascript, so it took me a while to learn the code, but this is a great library that is well planned and therefore easy to extend.

Much thanks to the developer(s)!
gbegley
April 16,

This topic is archived.

See also:


Back to support forum

Search

Version 2

Looking for AW 2.6 ?
The old site is here.