Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

layerDef for feature layer #357

Closed
lee53 opened this issue Jan 22, 2015 · 31 comments
Closed

layerDef for feature layer #357

lee53 opened this issue Jan 22, 2015 · 31 comments

Comments

@lee53
Copy link

lee53 commented Jan 22, 2015

Is there anyway I can set layer definition for feature layer in viewer.js?

such as:

{type: 'feature'
url: 'http://.........',
title: 'Incident within 24 hours'
setDefinitionExpression: 'IncidentAge<24',
}

@tr3vorm
Copy link
Contributor

tr3vorm commented Jan 22, 2015

Yes, create a function for the imageParameters and put it at the top in viewer.js. My function is setting the same layer definition query for the first 10 layers of the following mapservice.

      operationalLayers: [{
            type: 'dynamic',
            url: 'https://.../MapServer',
            title: 'Oil and Gas',
            collapsed: false,
            slider: false,
            options: {
                id: 'oag',
                opacity: 1.0,
                visible: true,
                imageParameters: buildImageParameters()
            }
        }]

    function buildImageParameters() {
        var ip = new ImageParameters();
        var key = 'layerDefinitions';
        for (var i = 0; i < 10; i++) {
            ip[key].push('IncidentAge < 24');
        }
        return ip;
    };

@green3g
Copy link
Member

green3g commented Jan 22, 2015

Feature layers do have a setDefinitionExpression method, but the only way I can see setting them currently would be to build a custom widget that has layerControlLayerInfos: true in the widgets options.

The widget would then have a postCreate method that calls the layers setDefinitionExpression method. I would eventually like to build a widget that ties in to the layer control allowing the user to select a feature layer, then apply definition expressions themselves..

Edit: thanks @tr3vorm I'll definitely find that helpful!

@lee53
Copy link
Author

lee53 commented Jan 22, 2015

@tr3vorm thanks. your example is for dynamic map service. can it be used for feature service?

@tr3vorm
Copy link
Contributor

tr3vorm commented Jan 22, 2015

I don't know sorry, I read that after I posted.

@lee53
Copy link
Author

lee53 commented Jan 22, 2015

@tr3vorm no problem. my idea is using a single map service (feature) and add multiple times with different layer definitions. for example incidents within 24 hours, within 1 week,...etc. I guess I can add multiple functions instead. @roemhildtg I think your idea is worthwhile to pursue. thank you.

@lee53
Copy link
Author

lee53 commented Jan 22, 2015

@tr3vorm where should I put the function buildimageparameter() in viewer.js?

@tmcgee
Copy link
Member

tmcgee commented Jan 22, 2015

I've contemplated a concept where you can add an optional object of event handlers to each operational layer. In this case, it might be something like:

events: {
   'load': function (lyr) {
      lyr.setDefinitionExpression('IncidentAge<24')
    },
    'click': function (evt) {
        ...
    }
},

then the Controller would loop through the events object and add each of them to the layer. Obviously the scope of the function would have to be taken into consideration. Thougths?

@tmcgee
Copy link
Member

tmcgee commented Jan 22, 2015

@lee53 check out issue #198

@green3g
Copy link
Member

green3g commented Jan 23, 2015

@tmcgee I think that would be a good alternative to writing a widget to handle this.

@tr3vorm
Copy link
Contributor

tr3vorm commented Jan 23, 2015

@lee53 At the start of the function declaration, which reminds me you will have to add ImageParameters

define([
    'esri/units',
    'esri/geometry/Extent',
    'esri/config',
    'esri/tasks/GeometryService',
    'esri/layers/ImageParameters',
    'esri/urlUtils',
    'esri/request'
], function (units, Extent, esriConfig, GeometryService, ImageParameters, urlUtils, request) {
    function buildImageParameters() {
             :
        return ip;
    };

@tmcgee I like your thinking.

@btfou
Copy link
Contributor

btfou commented Jan 23, 2015

@tmcgee
Copy link
Member

tmcgee commented Jan 23, 2015

@btfou I initially was thinking about something pretty much exactly like that but thought we may not want to limit it to just pre and load use cases.

A similar approach could be taken for widgets too. Devs could avoid creating and maintaining custom widgets when all they need is a minor tweak to an existing widget. Widget methods can already be overwritten within the config object. Responding to widget events could be a flexible addition.

@DavidSpriggs
Copy link
Member

I like this idea. I have had this same thought in the past (the ability to set custom event triggers/handlers via config). If we went this route, we would also need to include a property to let the user set the handler to fire once or every time the base event fires.

The downside, and why I did not pursue it earlier, is that we are removing the user from the code, they are not learning JS. Rather than learning JS they are learning a configuration syntax. There are arguments both ways and I totally get the use case, I just would rather have people learn JS ;)

On the up side, having a config with custom events that is portable to the next version of the viewer is a plus. This lowers the bar for non devs and makes upgrading less painful for minor tweaks.

Other thoughts?

@tmcgee
Copy link
Member

tmcgee commented Jan 23, 2015

@DavidSpriggs Thanks for chiming in from your alternate time zone.

I understand and completely agree with encouraging folks to learn JavaScript. You and I both know it is the ONLY viable future. ;)

For something like this, I don't think we are really making a choice between configuration syntax vs learning JavaScript. The method triggered by the event handler is JS either way. For me, it is a matter of providing options which is a positive for all. For a simple one-liner like this, if given the choice of creating a custom widget, modifying the controller or placing it in the config, I would use the config option strictly for the ease of code maintenance and upgrades. That's my 0.0000002 cents.

@jebu75
Copy link
Collaborator

jebu75 commented Jan 24, 2015

I think having the ability to affect MINOR tweaks to a widget thru configuration would be useful but I think any developer taking this approach needs to think about preventing the configuration from getting so overly complex and loaded that it in itself gets hard to maintain. When does it the config file become more than just a config file? Is overriding widget methods really a configuration? (not making a judgement, just wondering out loud).

I worry, mainly because I've fallen into this trap myself, that too many configuration options makes both the CMV code and my code harder to maintain, adapt and evolve going forward. Is there some threshold at which it makes more sense for a developer to extend a widget to customize the functionality versus CMV providing him with hundreds of configuration options?

CMV provides so many configurable options that in one application of mine, the configuration file is 670 lines of code, and that's with breaking out the widget configuration into separate classes! This app requires many operational layers and each needs to have constructor options and LayerController options. The configuration of the operational layers alone is ~400 lines of code. I have a standard set of widgets I use in multiple applications so I broke the widget configuration up into separate classes that I could just use in each app. I also have a proxy manager class that I use in multiple applications so if I hadn't broken those out, my config file could easily be 1000 lines of code.

@tmcgee
Copy link
Member

tmcgee commented Jan 24, 2015

I agree. Adding code to a config file would be appropriate for minor tweaks to a widget or a few lines of code to modify a layer like the original request. Something like the "buildImageParameters" function commonly included in the config file is a good example of an appropriate use in my mind. More than a few lines of code would most likely be better in a custom widget/class/module.

@hoomanmoh
Copy link

Hey, I was just wondering if the optional events object in config/viewer.js has been implemented or was it just a proposal? I'd love that idea, as I'm also in need of repeating a featurelayer with different definitionExpression in the viewer and want to avoid creating just a widget for that. Thanks

@tmcgee
Copy link
Member

tmcgee commented Mar 25, 2015

In my response to issue #399 I offered a simple "widget" written completely in viewer/config.js. Something like that may be suitable for this issue as well.

@saurabhgis
Copy link

I am trying to implement setDefinationExpression in feature layer but condition not working please check...

{
type: 'feature',
url: 'http://10.10.1.42:6080/arcgis/rest/services/xyz/MapServer/1',
title: 'District',

             setDefinitionExpression: "DIST_E = 'xyz'",
             options: {
                 id: 'District',
                 opacity: 1.0,
                 visible: true,
                 outFields: ['*'],
                 mode: 0,


             },
             editorLayerInfos: {
                 disableGeometryUpdate: false
             }
         },

@green3g
Copy link
Member

green3g commented Aug 26, 2016

Its a little tedious but you could try adding a new widget config like this:

setDefExpr: {
    include: true,
    id: 'setDefExpr',
    type: 'invisible',
    path: 'dijit/_WidgetBase',
    options: {
        layerControlLayerInfos: true,
        startup: function () {
            this.layerInfos[0].layer.setDefinitionExpression('DIST_E="xyz"');
        }
    }
}

@tmcgee
Copy link
Member

tmcgee commented Aug 26, 2016

@saurabhgis I find a simple widget like the one provided by @roemhildtg to be the most flexible option.

@triesco
Copy link

triesco commented Sep 22, 2016

@roemhildtg How do you implement this widget? Do you set this in viewer.js under the widget list? Thanks!

@green3g
Copy link
Member

green3g commented Sep 23, 2016

Yep, you'd just add it to your widgets object.

@triesco
Copy link

triesco commented Sep 23, 2016

So for this.layerInfos[0].layer.setDefinitionExpression('DIST_E="xyz"');
0 is the id of the layer to set the definitionexpression?
Im getting an array of objects on the console but not setting the definition for the layer that I want. Any more ideas?
Thanks!

@tmcgee
Copy link
Member

tmcgee commented Sep 24, 2016

@triesco 0 in the index into the layerInfos array. That means it is retrieving the first layer in that array. If your feature layer is not the first layer, you will need to adjust accordingly. An alternative approach using the layer's id would be:

setDefExpr: {
    include: true,
    id: 'setDefExpr',
    type: 'invisible',
    path: 'dijit/_WidgetBase',
    options: {
        map: true,
        startup: function () {
            var layer = this.map.getLayer('layerID'); // put your layer ID here
            layer.setDefinitionExpression('DIST_E="xyz"');
        }
    }
}

@tmcgee tmcgee closed this as completed Sep 26, 2016
@triesco
Copy link

triesco commented Sep 28, 2016

@tmcgee Thanks. I tried this approach and still not setting the definition. Console does point to the correct layer but skips the setDifinitionExpression. I also get a Error: Cannot perform query. Invalid query parameters.

@triesco
Copy link

triesco commented Sep 28, 2016

Found the error. Should be layer.setDefinitionExpression("DIST_E = 'xyx'") instead of ('DIST_E="xyz"') Single and double quotes issue.

@cmccullough2
Copy link

I have been able to successfully a setDefinitionExpression for an individual feature layer. However, I am receiving errors upon rendering. I am not sure why this is occurring. In addition, I need to add fields to the expression; . And, I need to add additional layers to the expression; [0,1,2,3,4,5,6,7,8,9,10,11,12]

Error Image:
image

Working code:
Operational Layers:
{
type: 'feature',
url: 'https://idpgis.ncep.noaa.gov/arcgis/rest/services/NWS_Observations/ahps_riv_gauges/MapServer/0',
title: i18n.viewer.operationalLayers.nwsObservations,
options: {
id: 'nwsObservations',
opacity: 1.0,
visible: true,
outFields: ['*'],
imageParameters: buildImageParameters({
layerIds: [0],
layerOption: 'show'
})
},
layerControlLayerInfos: {
layerGroup: 'Weather Layers'
}
},
Widgets:
setDefExpr: {
include: true,
id: 'setDefExpr',
type: 'invisible',
path: 'dijit/_WidgetBase',
options: {
map: true,
startup: function () {
var layer = this.map.getLayer('nwsObservations'); // put your layer ID here
layer.setDefinitionExpression("status = 'action'");
}
}
},

@tmcgee
Copy link
Member

tmcgee commented Sep 5, 2017

@cmccullough2 I can't say for sure but I believe those errors are to be expected. I see those when the requests for features from the layer are interrupted by a new set of requests for features from the same layer - quite possibly because of the change if the definition expression.

I don't completely understand what you are asking when you say:

And, I need to add additional layers to the expression; [0,1,2,3,4,5,6,7,8,9,10,11,12]

A feature layer is specific to one sub layer so you can't add additional layers to that feature layer. If you need to filter multiple sublayers with a definition expression, consider using a dynamic layer instead of a feature layer.

@cmccullough2
Copy link

@tmcgee sorry I was not so clear with my question. I was able to work with the feature layer, but it kept breaking when I tried to use a dynamic layer. I will try again. :) Thank you for the information with the errors.

@green3g
Copy link
Member

green3g commented Sep 5, 2017

@cmccullough2 you might also have luck diagnosing the issue by looking at the network log. The request cancelled may indicate an error on the server side while processing the definition expression.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests