Print Tool: BuildSpecModel.getStylingRules - Uncaught TypeError: t.reduce is not a function

Issue #703 closed
Former user created an issue

sollte styleAttr mit dem Wert "styleId" gesetzt werden, so kommt es im Anschluss beim Aufruf der reduce() Methoden zum Fehler, da styleAttr kein Array ist. https://bitbucket.org/geowerkstatt-hamburg/masterportal/src/dev/src/modules/tools/print/utils/buildSpec.js

masterportal.js:185 Uncaught TypeError: t.reduce is not a function at t.getStylingRules (masterportal.js:185:350386) at masterportal.js:185:344132

getStylingRules: function (layer, feature, styleAttributes, style) {
        const layerModel = Radio.request("ModelList", "getModelByAttributes", {id: layer.get("id")}),
            styleAttr = feature.get("styleId") ? "styleId" : styleAttributes;

Reproduziert werden kann dies auffälligerweise Wenn Zeichnungen gedruckt werden sollen.

  /**
     * Returns the rules for styling of a feature
     *
     * @param {ol.Feature} layer -
     * @param {ol.Feature} feature -
     * @param {String[]} styleAttributes The attribute by whose value the feature is styled.
     * @param {ol.style.Style} style style
     * @returns {string} an ECQL Expression
     */
    getStylingRules: function (layer, feature, styleAttributes, style) {
        const layerModel = Radio.request("ModelList", "getModelByAttributes", {id: layer.get("id")}),
            styleAttr = feature.get("styleId") ? ["styleId"] : styleAttributes;
        let styleModel,
            labelField,
            labelValue;

        console.log(styleAttr);

        if (styleAttr.length === 1 && styleAttr[0] === "") {
            if (feature.get("features") && feature.get("features").length === 1) {
                const singleFeature = new Feature({
                    properties: feature.get("features")[0].getProperties(),
                    geometry: feature.get("features")[0].getGeometry()
                });

                feature.get("features")[0] = singleFeature;
                if (style.getImage().getSrc().indexOf("data:image/svg+xml;charset=utf-8") === 0) {
                    singleFeature.setId("first_svg_" + singleFeature.ol_uid);
                }
                else {
                    singleFeature.setId("second_png_" + singleFeature.ol_uid);
                }
                singleFeature.set(singleFeature.getId(), String(feature.get("features").length));
                return "[" + singleFeature.getId() + "='" + String(feature.get("features").length) + "']";

            }
            if (feature.get("features") !== undefined) {
                if (style !== undefined && style.getText().getText() !== undefined) {
                    feature.set("sensorClusterStyle", feature.get("features")[0].ol_uid + "_" + String(style.getText().getText()));
                    return "[sensorClusterStyle='" + feature.get("features")[0].ol_uid + "_" + String(style.getText().getText()) + "']";
                }
            }

            return "*";
        }
        // cluster feature with geometry style
        if (feature.get("features") !== undefined) {
            if ((style !== undefined && style.getText().getText() !== undefined) || feature.get("features").length > 1) {
                const value = feature.get("features")[0].get(styleAttr[0])
                    + "_"
                    + style !== undefined && style.getText().getText() !== undefined ? style.getText().getText() : "cluster";

                feature.set(styleAttr[0], value);
                return `[${styleAttr[0]}='${value}']`;

            }

            // Current feature is not clustered but a single feature in a clustered layer
            return styleAttr.reduce((acc, curr) => {
                const value = feature.get("features")[0].get(curr);

                feature.set(curr, value);
                return acc + `${curr}='${value}',`;
            }, "[").slice(0, -1) + "]";
        }
        // feature with geometry style and label style
        if (layerModel !== undefined && Radio.request("StyleList", "returnModelById", layerModel.get("styleId")) !== undefined) {
            styleModel = Radio.request("StyleList", "returnModelById", layerModel.get("styleId"));

            if (styleModel !== undefined && styleModel.get("labelField") && styleModel.get("labelField").length > 0) {
                labelField = styleModel.get("labelField");
                labelValue = feature.get(labelField);
                return styleAttr.reduce((acc, curr) => acc + `${curr}='${feature.get(curr)}' AND ${labelField}='${labelValue}',`, "[").slice(0, -1)
                    + "]";
            }
        }
        // feature with geometry style
        return styleAttr.reduce((acc, curr) => acc + `${curr}='${feature.get(curr)}',`, "[").slice(0, -1)
            + "]";
    },

Comments (11)

  1. Patrick

    beim Erfassen des Bugs ist leider der notdürftige Fix

    styleAttr = feature.get("styleId") ? ["styleId"] : styleAttributes;
    

    rein gerutscht.

    Der aktuelle Code sieh so aus:

      styleAttr = feature.get("styleId") ? "styleId" : styleAttributes;
    

  2. Klara Böcker

    Hallo, können Sie den Fehler in der aktuellen Versin noch nachstellen? Ich kann den Fehler so erstmal nicht nachstellen.

    VG

  3. Patrick

    Das Problem besteht weiterhin.

    Die Zeile

    const styleAttr = feature.get("styleId") ? "styleId" : styleAttributes,
                styleModel = this.getStyleModel(layer);
    

    führt dazu, dass in der Variable styleAttr ggf. der String "styleId" steht.

    Dies führt dazu, dass später auf dieser Variable die Methdode reduce() aufgerufen wird in der Annahme, es sei ein Array

    Vermutlich sollte nach der Prüfung feature.get("styleId") dieser Wert statt nur der Key gesetzt werden:

    const styleAttr = feature.get("styleId") ? feature.get("styleId")  : styleAttributes,
                styleModel = this.getStyleModel(layer);
    

    3 x wird reduce auf styleAttr aufgerufen:

    1)

     return styleAttr.reduce((acc, curr) => {
                    const value = feature.get("features")[0].get(curr);
    

    2)

       return styleAttr.reduce((acc, curr) => acc + `${curr}='${feature.get(curr)}' AND ${labelField}='${feature.get(labelField)}',`, "[").slice(0, -1)
                    + "]";
    

    3)
    nur im 3. Fall wird geprüft, ob styleAttr ein Array ist. Ggf. ist dies aber ein String mit dem Wert “styleId”

      if (styleAttr instanceof Array) {
                return styleAttr.reduce((acc, curr) => acc + `${curr}='${feature.get(curr)}',`, "[").slice(0, -1)
                + "]";
            }
    

  4. Klara Böcker

    Hallo Patrick, hast du eine Konfiguration/einen Use Case mit dem wir das Verhalten nachstellen können? Tritt das bei einem bestimmten Layer auf?

    Wenn du willst, kannst du das auch fixen und einen PR stellen?

  5. Klara Böcker

    Was genau zeichnest du denn? Ich habe mal “simple” Zeichnungen ausprobiert und bei mir läuft alles. Ich hänge meine Ausdrucke mal an.

  6. Patrick

    Vielen Dank Klara für die Antworten.

    Die Ursache war eine Kombination aus dem Backend und dem Printtemplate.

    Das Ticket kann geschlossen werden.

  7. Log in to comment