Afficher les infos d'une couche WFS dans un popup

Introduction


L'API d'OpenLayers permet d'afficher une couche WFS ainsi que les données attributaires qui lui sont rattachées. Même si cela n'est pas très compliqué à réaliser il existe certaines subtilités.

La couche WFS


L'affichage d'une couche WFS depuis OpenLayers se fait comme n'importe qu'elle autre couche à ceci prêt que nous allons, pour les besoins de ce tutoriel, spécifier un attribut supplémentaire qu'est extractAttributes. Celui-ci est optionnel mais il permet de parser le flux WFS afin d'extraire les données attributaires. A noter que cela ralentit le traitement cartographique.

var africaWFS = new OpenLayers.Layer.WFS(
   "Africa WFS",
   "http://pathToMapServ/mapserv?map=/pathToYourMapFile/africa.map&",
   {typename: 'Africa'},
   {style: fStyle, extractAttributes: true}
 );

Bien entendu il est nécessaire que votre moteur cartographique soit configuré pour envoyer des données attributaires. Dans le cas de MapServer n'oubliez pas de définir pour vos couches les paramètres DUMP et gml_include_items (voir MapServer WFS)

LAYER
	NAME Africa
	STATUS ON 
	METADATA
		### WMS 
		"wms_title"    "Africa" 
		### WFS 
		"wfs_title"    "Africa" 
    		"gml_featureid" "NAME" 
    		"gml_include_items" "all"
	END
	PROJECTION
		"init=epsg:4326"
	END
	DUMP TRUE
	TYPE POLYGON
	STATUS ON
	DATA africa
	CLASS
		COLOR 217 217 217
		OUTLINECOLOR 0 0 0 
	END

Extraire les données attributaires


Pour accéder aux données d'une couche WFS vous devez spécifier la propriété attributes suivi du nom de la balise XML que vous souhaitez afficher (qui est égal à son nom dans la table attributaire mais en majuscule). Par exemple si dans votre flux il existe une valeur "NAME" pour l'afficher vous devrez faire monObjetWFS.attributes.NAME

Enfin, en toute logique votre PopUp se déclenchera sur une action (cf selectFeature). Dans ce cas, la fonction à laquelle renvoie le listener inclut directement l'objet WFS. C'est un peu confus à expliquer mais vous comprendrez mieux dans l'exemple ci-dessous :

function init() { 
    /*
     * Some code before
     */
    // Instanciation du control selectFeature
    options = {       
         hover: false,
         // Fait reference a la fonction popUp
         onSelect: popUP,
         selectStyle :feature_style
    };     
    sf = new OpenLayers.Control.SelectFeature(africaWFS, options)
    map.addControl(sf);
    sf.activate();
}
 
function popUP(e) {
   // Je verifie qu'aucun popup n'existe deja
   if(typeof popup!='undefined'){
         popup.destroy();
    }
    //je definis les params de mon popup
    var htmlContent = "<b>Pays : "+e.attributes.NAME+"</b><br /> <b><i>Region : "+e.attributes.REGION+"</b></i>";       
    var size = new OpenLayers.Size(20,34);
    var offset = new OpenLayers.Pixel(-(size.w/2), -size.h);
    //j'instancie mon popup
    popup = new OpenLayers.Popup.FramedCloud(
         e.fid,
         e.geometry.getBounds().getCenterLonLat(),
         null,
         htmlContent,
         null,
         false,
          null
    );
    //Je l'ajoute a la carte
    map.addPopup(popup);                  
}

Exemple


Bonjour, J'ai lu avec

Bonjour,

J'ai lu avec beaucoup d'intérêt votre tuto.

J'ai une petite question.
J'ai plusieurs couches WFS (une centaine) avec beaucoup d'attributs.

J'aimerais savoir si vous savez comment exploiter les données de e.attributes sans connaitre leur valeur.

Par exemple à la place de :
e.attributes.NAME on pourrait avoir e.attributes[0] (cette méthode ne marche pas...)
Pareil peut on connaitre le nombre d'attributs d'un objet ?

Merci beaucoup

Nicolas

Voilà ce que je souhaite

Voilà ce que je souhaite faire :
dans une couche WFS, j'ai des polygones qui peuvent se superposer (partiellment, inclusion totale...). Ainsi si je met en place un featureSelect, je ne sais pas lequel des polygones va etre sélectionné en fonction de l'ordre d'empilement.
Donc je voudrais, sur click, ouvrir une popup qui m'affiche la liste les polygones sous le click, pour choisir celui que je veux effectivement sélectionner.
Comment faire ?

Bonjour, J'ai suivi le

Bonjour,

J'ai suivi le tutorial mais j'ai un petit problème : je n'arrive pas à afficher les attributs dans la popup (il me met "undefined"). Je les stocke dans une table PostGIS sous les noms de id et name, et je les appelle avec e.attributes.ID et e.attributes.NAME.

Une idée de quoi ça pourrait venir ?

Merci pour vos tutoriaux bien intéressants !

Et je confirme le commentaire précédent: lors de la fermeture d'un popup, l'objet reste actif.

Bonjour, Dans votre layer

Bonjour,

Dans votre layer avez-vous bien défini la propriété "extractAttributes: true"?

Arnaud

Very good post, thanks a lot.

Very good post, thanks a lot.

Oui, je la crée comme ça

Oui, je la crée comme ça :

var wfs_points = new OpenLayers.Layer.WFS(
  "Points",
  "http://vdepgbovard/geoserver/wfs",
  {
    typename: "test:points",
    extractAttributes: true
  }
);

Le contrôle select :

select: new OpenLayers.Control.SelectFeature(
  wfs_points,
  {
    displayClass: "olControlSelect",
    onSelect: displayInfos
  }
),

Et la fonction displayInfos :

function displayInfos(e) {
 
  // Check if a popup exists
  if (typeof popup != "undefined") {
    popup.destroy();
  }
 
  // Set content of popup
  var htmlContent = "ID : <strong>" + e.attributes.ID + "</strong><br />Name : <strong>" + e.attributes.NAME + "</strong>";
 
  popup = new OpenLayers.Popup.FramedCloud(
    e.fid,
    e.geometry.getBounds().getCenterLonLat(),
    null,
    htmlContent,
    null,
    true,
    null
  );
 
  map.addPopup(popup);
}

Merci !

Il faudrait peut être essayer

Il faudrait peut être essayer de voir si ID et NAME ne doivent pas être en minuscules.
De plus pour voir quel objet est envoyé il faudrait faire un console.log(e) dans la fonction displayInfos. Ainsi nous en saurons un peu plus.

Arnaud

Bonjour, Alors en mettant les

Bonjour,

Alors en mettant les attributs en minuscules ça marche partiellement...

Pour le test j'ai ajouté des colonnes à ma table PostGIS et ça confirme ce que je pensais: j'arrive à extraire qu'un seul attribut !? En testant avec console.log(e.attributes) je n'obtiens que le champ name et pas les autres (id, text, abc).

Est-ce qu'il faut spécifier une option pour pouvoir extraire plusieurs attributs ?

Merci pour les réponses rapide !

Non normalement la seule

Non normalement la seule chose que fait OpenLayers s'est de parser le flux. Donc si les données n'y sont pas cela provient du serveur carto. Comment est configuré votre mapfile?
Avez-vous bien défini les options de "gml_include_items" "all" ?

Arnaud

Bonjour, Alors j'ai trouvé

Bonjour,

Alors j'ai trouvé d'où venait le problème. En fait il fallait créer la couche OpenLayers avec des éléments spécifiques à GeoServer pour que ça fonctionne :

var wfs_points = new OpenLayers.Layer.WFS(
  "Points",
  "http://vdepgbovard/geoserver/wfs",
  {
    typename: "test:points"
  },
  {
    typename: "points",
    extractAttributes: true
  }
);

"test" étant l'espace de nommage GML paramétré dans GeoServer.

Merci encore pour votre réactivité :D

Bonjour, je suis au fil

Bonjour,
je suis au fil du temps vos tuto qui m'apprennent beaucoup. Niveau des fenêtres popUp y t'il moyen d'insérer un bouton fermer dedans.

Bonjour, Il est tout à fait

Bonjour,

Il est tout à fait possible d'ajouter une close box à votre popup. Cet option peut être définie par défaut dans le constructeur : API OL.

closeBox : {Boolean} Whether to display a close box inside the popup.

Oui j'ai trouvé la solution

Oui j'ai trouvé la solution merci, il y a un autre paramètre qui permet d'appeler une fonction à la fermeture moi je suis appelé une fonction qui me déselectionne l'objet en même temps que la fermeture mais du coup ca me bloque la fermeture etc...
Voici le code de ma fonction:

function onPopupClose() {
selectControl.unselect(selectedFeature);
}

merci

Bonjour, Normalement il n'y

Bonjour,

Normalement il n'y a pas besoin d'effectuer une déselection. OpenLayers le fait par défaut.

Il ne le fait pas chez moi!

Il ne le fait pas chez moi! pourtant j'utilise la dernière version