quick q: how to display ALL fields in esri.dijit.Popup

4954
17
04-22-2013 12:07 PM
KevinMacLeod1
Occasional Contributor III
Hi all,

I want to display all attributes for all fields in an esri.dijit.Popup window.

I remember seeing this somewhere but can not find it again. I want to accomplish the same thing the following code would do in a regular infoWindow:

var infoTemplate = new esri.InfoTemplate("${name}", "${*}");

But with a Popup Dijit. Anyone know the syntax? Thanks!





Below is the entire code / details for why/what I am trying to accomplish. I want to convert the code below to a Popup dijit and put a 'title' in as a Description since it overwrites the title because it shows multiple coincident features.

       var infoTemplate = new esri.dijit.PopupTemplate({
                            title: "",
                            description: feature.attributes.layerName,
                            fieldInfos: [
                            { fieldName: "${*}", visible: true, label: "{*}" }
                            ]
                        });




I want to make that work in the identify widget:
//// Identify Widget ////
        var identifyParams;
        var tasks;
        var clickPoint;

            //var popup = new esri.dijit.Popup({ fillSymbol: new esri.symbol.SimpleFillSymbol(esri.symbol.SimpleFillSymbol.STYLE_SOLID, new esri.symbol.SimpleLineSymbol(esri.symbol.SimpleLineSymbol.STYLE_SOLID, new dojo.Color([255, 0, 0]), 2), new dojo.Color([255, 255, 0, 0.25]))}, dojo.create("div"));


        dojo.connect(map, 'onLoad', function () {
            //setup generic identify parameters 
            identifyParams = new esri.tasks.IdentifyParameters();
            identifyParams.tolerance = 5;
            identifyParams.returnGeometry = true;
            identifyParams.layerIds = MYDYNAMICLAYER.visibleLayers;
            identifyParams.layerOption = esri.tasks.IdentifyParameters.LAYER_OPTION_VISIBLE;

            dojo.connect(map, 'onClick', doIdentify);
        });





        dojo.connect(map, 'onLayersAddResult', setupIdentify);


        function setupIdentify(results) {
            //loop through operational layers and add identify task for each. 
            tasks = dojo.map(results, function (result) {
                return new esri.tasks.IdentifyTask(result.layer.url);
            });


        }
        function doIdentify(evt) {

            map.infoWindow.hide();
            clickPoint = evt.mapPoint;

            identifyParams.geometry = evt.mapPoint;
            identifyParams.mapExtent = map.extent;
            identifyParams.width = map.width;
            identifyParams.height = map.height;
            identifyParams.layerIds = MYDYNAMICLAYER.visibleLayers;
            identifyParams.layerOption = esri.tasks.IdentifyParameters.LAYER_OPTION_VISIBLE;

            var deferreds = dojo.map(tasks, function (task) {
                return task.execute(identifyParams);
            });
            var dlist = new dojo.DeferredList(deferreds);
            dlist.then(handleQueryResults);

        }
        function handleQueryResults(results) {

            var features = [];
            dojo.forEach(results, function (result) {
                // for a simplified test let's just display all the attributes in the popup 
                if (result[1].length > 0) {
                    dojo.forEach(result[1], function (r) {
                        var feature = r.feature;
                        console.log(feature);
                        feature.attributes.layerName = r.layerName;


                        var infoTemplate = new esri.InfoTemplate("${name}", "${*}");
                        

                        feature.setInfoTemplate(infoTemplate);
                        features.push(feature);

                    });
                }

            });
            map.infoWindow.setFeatures(features);
            map.infoWindow.show(clickPoint);

        }


        //// ^^^  Identify Widget ////
0 Kudos
17 Replies
KevinMacLeod1
Occasional Contributor III
Still working on this... I have tested inserting the following code at http://jsfiddle.net/URpaW/

Replacing what was there, the infoTemplate, at line 101

      var infoTemplate = new esri.dijit.PopupTemplate({
                            description: feature.attributes.layerName,
                            fieldInfos: [{
                                fieldName: "*",
                                visible: true,
                                label: "*"
                            }]
                        }); 


This only displays the description, though. When I delete "description: feature.attributes.layerName," though it displays all fields. Although it displays an asterisk for a label, as well.

Anyone else using this approach for their popups / Identify tools and know the syntax?
0 Kudos
derekswingley1
Frequent Contributor
It is a bad idea to show all fields in an info window or popup. Showing all fields puts (what is likely) unnecessary info (objectid as well as shape, shape_area and shape_length fields, unformatted field names, others depending on the app) next to important info and clutters the popup. Your best bet, especially in terms of app usability, is to come up with a list of fields to display for each layer and conditionally create and set popup templates for features. It's more work for you, but it's a better experience for your users.
0 Kudos
KevinMacLeod1
Occasional Contributor III
Hi Derek, thank you for your reply.

I am with you on the UI aspect. However, it's over 100 layers each with 15+ fields and many may change soon so this is the best approach for now for us.  The esri.dijit.PopupTemplate can do this, it does support wildcards for all fields, just like infoTemplate, right? InfoTemplate works great but Popup is just better. I recall having found the Popup syntax before but can not locate it again, if you could provide this syntax that would be kindly appreciated!

I wonder whether using wildcards and some fancy array syntax / logic it would be possible to say show me everything BUT the ObjectID and Shape? It's fine they are there, it's much more important to show all fields than worry about those two, but that would be a neat trick.
0 Kudos
ReneRubalcava
Frequent Contributor
I put this little helper module a while ago and use it regularly to filter build my InfoTemplates. You might find it useful.
https://github.com/odoe/agsnode-dev/blob/master/public/javascripts/helpers/templateBuilder.js

Actually, looking at that, I updated it with updates I made to accept options for a URL field.
0 Kudos
derekswingley1
Frequent Contributor

I am with you on the UI aspect. However, it's over 100 layers each with 15+ fields and many may change soon so this is the best approach for now for us.  The esri.dijit.PopupTemplate can do this, it does support wildcards for all fields, just like infoTemplate, right?

Yes, it can be done but it looks terrible and is hardly readable. This is what you're missing:
var infoTemplate = new esri.dijit.PopupTemplate({
  title: feature.attributes.layerName, 
  description: "{*}"
});
0 Kudos
KevinMacLeod1
Occasional Contributor III
Derek thank you so much, indeed this works. Although I wonder why it does not make the field name's "label" and its contents justify to the left/right, kind of split, like most esri.dijit.PopupTemplate windows? And where the field name label is grey? Like on ArcGIS.com. Is that not possible when telling it to use all fields in the description via wildcard?

Odoe thank you for your advice, too. I'm still in the learning phase here, hope to be a helpful contributor and adviser here myself in the future.

If I understand your code Odoe, it displays all attributes in the popup dijit infowindow... but strips out the ObjectID and FID fields? This sounds perfect. I think I see the pattern where I could add others to ignore like Shape as well.

Generally, how do we use it? Is this an object I make an instance of, like AGS JS TOC widget for example? So, we put it at the top of our code (i.e. the 'layout.js' or equivalent where the script is located)? How do we tell it which layer(s) to use? I'd love to implement your utility. I'm starting to experiment with it.  Thanks both!
0 Kudos
ReneRubalcava
Frequent Contributor
The way I use it is either on a "onClick" event of a GraphicsLayer or FeatureLayer or an IdentifyTool.
You would iterate over your results or FeatureSet so something like

define(['dojo/_base/array', 'helpers/templateBuilder'], function(array, templateBuilder) {
// do something on a click or identify
  array.forEach(featureSet, function(feat) {
    feat = templateBuilder.buildInfoTemplate(feat);
  });
// do something for results
});



This piece here is where all the work is done.

var content = [],
                urlField = options ? options.urlField : '', // you can include url info in options
                urlPrefix = options ? options.urlPrefix : ''; // you can include url info in options
            // get the dom element for my infotemplate as a string
            content[content.length] = '<table cellspacing="0" class="table table-striped table-condensed attr-info">';
            if (feature.layerName) {
                content[content.length] = '<tr><td class="fieldName">SOURCE: </td><td class="fieldName">' + feature.layerName + '</td></tr>';
            }
            /**
            * Iterate over attributes to get field names.
            * Ignore certain fields not needing to be displayed
            * Order matters, so loop forward over keys.
            **/
            var keys = Object.keys(feature.attributes),
                i = 0,
                len = keys.length;
            // This is where al the real work is done.
            for (; i < len; i++) {
                var _key = keys.toLowerCase(),
                    name;
                // add any other values you want to ignore into this if statment || _key === 'objectid2' for example
                if (!(_key.indexOf('shape') > -1 || _key === 'layername'|| _key === 'objectid' || _key === 'fid')) {
                    name = keys;
                    if (name.toLowerCase() !== urlField) {
                        content[content.length]= '<tr><td class="fieldName">' + name + '</td><td>${' + name + '}</td></tr>';
                    } else {
                        content[content.length] = '<tr><td class="fieldName">' + name + '</td><td><a href="' + urlPrefix + '${' + name + '}">${' + name + '}</a></td></tr>';
                    }
                }
            }
            content[content.length] = '</table>';


I don't have a sample on hand, but if you wanted to use this to assign to an InfoTemplate to the whole FeatureLayer, you need the fields info from a FeatureLayer
http://developers.arcgis.com/en/javascript/jsapi/featurelayer.html#fields
Tweak the code to iterate over the field values. Now that I think about it, I like that idea better... I'll probably refactor this to handle an array of fields and make it useable in varying scenarios...

But I hope that helps a little bit.
0 Kudos
AdrianMarsden
Occasional Contributor III
I don't use the popup thingy at all  - I redirect all to a floating pane and then go through each found layer, and each result in the layer to produce something like the attached - basically replicating what we had in ArcIMS 🙂

[ATTACH=CONFIG]23880[/ATTACH]

So it is important to only expose the fields you want to see in the ArcMap MXD.  By using the layer description I have also manage a feature specific hyperlink (again like ArcIMS)

Shout if you want to see the code

ACM
0 Kudos
KevinMacLeod1
Occasional Contributor III
I don't use the popup thingy at all  - I redirect all to a floating pane and then go through each found layer, and each result in the layer to produce something like the attached - basically replicating what we had in ArcIMS 🙂

[ATTACH=CONFIG]23880[/ATTACH]

So it is important to only expose the fields you want to see in the ArcMap MXD.  By using the layer description I have also manage a feature specific hyperlink (again like ArcIMS)

Shout if you want to see the code

ACM


ACM and all thank you so much. Very cool example.

Hm. I do have access to the MXD and all server capabilities. I talked to someone today who said if I hide the field in ArcMap (hide the column in attribute table) it will hide it from showing up. The server is processing something now, so I can not test this, but I will test it in the next few days and report back on its success.
0 Kudos
AdrianMarsden
Occasional Contributor III
Yep, that's right, only fields in the MXD will get exposed - plus they will have any aliases you set in ArcMap as well.  ArcServer gets a bit stressed if you don't expose the shape filed and always leave OBJECTID 9or whatever your unique key is) but otherwise hide anything that you don't think will be used.

If I have time I'll package my "everything in one floating pane" code up with an Esri example some time.

ACM
0 Kudos