Forum Discussion

Anonymous's avatar
Anonymous
Not applicable
6 years ago
Solved

Circle Card showing two field values

I just started developing a custom visual, a circle card to show two field values.  Both fields are coming from the same data source (.csv) file. May i know the best approach to implement the dataRoles in the capabilities.json?

  • dm-p's avatar
    dm-p
    6 years ago

    Hi Anonymous,

    Glad you found it useful! I'm unfortunately not 100% clear on your follow-up question, so I'll take a broad approach and maybe the answer is in there somewhere - apologies in advance if I'm telling you stuff you already know 🙂

    The kind property really specifies what options are available to the end-user when they see the field in the properties pane, and how it can be mapped later on.

    Let's say I have a textual field, called City (it's one I have on hand in my data model at present).

    Specifying Grouping (either on its own or as GroupingOrMeasure) will allow the user to specify whether to summarise the value or not in the properties pane, e.g.:

    There is some expectation that you'll need to handle this somehow in your dataViewMapping also.

    Specifying Measure for kind is a way of telling the properties pane that this is purely an aggregated value, so only offer-up the options to the end-user that make sense here. For the same textual field we now don't see the option to summarise, e.g.:

    The doc is not 100% correct on this, and specifies Measure is for numeric values. I might have to figure out how to submit corrections to see if this can be cleared up.

    So with that in mind, don't think of Measure as a data model measure, more that "this data role should aggregate however it can, based on its type". For numeric values, you'll get the standard numeric ones such as min, max etc.; for textual fields we get the ones above. This is how the circle card tutorial is set up, and also how the core card visual works when you add textual fields to them.

    My Approach for your Visual

    When you want to use multiple data roles, this is where we can get creative with the categorical dataViewMapping. We don't have to specify a categories grouping as long as there's a valid binding to values, so I would firstly revise the dataRoles for your case as follows:

    "dataRoles": [
        {
            "displayName": "Station ID",
            "name": "stationID",
            "kind": "Measure"
        },
        {
            "displayName": "Throughput",
            "name": "throughput",
            "kind": "Measure"
        },
        {
            "displayName": "Status",
            "name": "status",
            "kind": "Measure"
        },
        {
            "displayName": "Color",
            "name": "color",
            "kind": "Measure"
        }
    ],

    I'd then set up my dataViewMappings as follows:

    "dataViewMappings": [
        {
            "categorical": {
                "values": {
                    "select": [
                        {
                            "bind": {
                                "to": "stationID"
                            }
                        },
                        {
                            "bind": {
                                "to": "throughput"
                            }
                        },
                        {
                            "bind": {
                                "to": "status"
                            }
                        },
                        {
                            "bind": {
                                "to": "color"
                            }
                        }
                    ]
                }
            }
        }
    ]

    Note that I'm not using a categories key, just a values one (as I don't need to be doing any grouping for a "single" data point).

    Now, when I refresh my visual and add my data, the dataView will now resolve as follows:

    I'm just using whatever data I have in my model but yours should resolve similarly. Notice that everything is consolidated in the values object.

    In terms of how you then access in your code thereafter, you'd swap out any instances of where you're referring to the categories object (e,g, for stationText and stationValue) and map them to the appropriate entry in the values object array instead.

    Let me know if there's anything in here that doesn't make sense and I'll do my best to provide more targeted feedback 😉

    Good luck!

    Daniel

8 Replies

  • dm-p's avatar
    dm-p
    Super User

    Hi Anonymous,

    If you're using the circle card tutorial as a reference point, this uses the single dataViewMapping, and this only ever supports one dataRole.

    To allow more values, you'll indeed need to add a new dataRole, but also change your dataViewMapping to something else, likely categorical and map the values accordingly.

    I have set up something similar in the past, with a tutorial, which does show how to convert the dataViewMapping across and might be something you can use to refer to. It's a little out of date, as the SDK has changed since I wrote and in this case, so you won't be able to lift and shift exaclty as coded, and the field is used for a tooltip but the premise is the same.

    Hopefully this will help you get started. Good luck!

    Daniel

    • Anonymous's avatar
      Anonymous
      Not applicable

      I really appreciate your help!  This is what i got in the capabilities.json and in the Visual.ts i have the below in the update method.   Is it really mandatory to have a grouping if we end up multiple measures? Actually i just want to show the normal field value not really a measure from the data model.

       

      "dataRoles": [
              {
                  "displayName": "Station ID",
                  "name": "stationID",
                  "kind": "GroupingOrMeasure"
              },
              {
                  "displayName": "Throughput",
                  "name": "throughput",
                  "kind": "Measure"
              },
              {
                  "displayName": "Status",
                  "name": "status",
                  "kind": "Measure"
              },
              {
                  "displayName": "Color",
                  "name": "color",
                  "kind": "Measure"
              }
      
          ],

       

       

       

          this.circle
                  .style("fill", categoricalDataView.values[2].values[0] as string)
                  .style("fill-opacity", 1)
                  .style("stroke", "black")
                  .style("stroke-width", this.visualSettings.circle.circleThickness)
                  .attr("r", radius)
                  .attr("cx", width/2)
                  .attr("cy", height/2);
      
              let fontSizeValue: number = Math.min(width, height) / 5;
      
              this.stationText
                  .text(categoricalDataView.categories[0].values[0] as string)
                  .attr("x", width/2)
                  .attr("y", height/10)
                  .attr("dy", "0.35em")
                  .attr("text-anchor", "middle")
                  .style("font-size", fontSizeValue / 2 + "px");
      
              this.stationValue
                  .text(categoricalDataView.categories[0].values[0] as string)
                  .attr("x", "50%")
                  .attr("y", "35%")
                  .attr("dy", "0.35em")
                  .attr("text-anchor", "middle")
                  .style("font-size", fontSizeValue / 2.5 + "px");
      
              this.throughputValue
                  .text(categoricalDataView.values[0].values[0] as string)
                  .attr("x", width/2)
                  .attr("y", height/2)
                  .attr("dy", "0.35em")
                  .attr("text-anchor", "middle")
                  .style("font-size", fontSizeValue + "px");
      
              this.statusValue
                  .text(categoricalDataView.values[1].values[0] as string)
                  .attr("x", "50%")
                  .attr("y", "55%")
                  .attr("dy", fontSizeValue / 1.2)
                  .attr("text-anchor", "middle")
                  .style("font-size", fontSizeValue / 2.5 + "px");

       

       

      • dm-p's avatar
        dm-p
        Super User

        Hi Anonymous,

        Glad you found it useful! I'm unfortunately not 100% clear on your follow-up question, so I'll take a broad approach and maybe the answer is in there somewhere - apologies in advance if I'm telling you stuff you already know 🙂

        The kind property really specifies what options are available to the end-user when they see the field in the properties pane, and how it can be mapped later on.

        Let's say I have a textual field, called City (it's one I have on hand in my data model at present).

        Specifying Grouping (either on its own or as GroupingOrMeasure) will allow the user to specify whether to summarise the value or not in the properties pane, e.g.:

        There is some expectation that you'll need to handle this somehow in your dataViewMapping also.

        Specifying Measure for kind is a way of telling the properties pane that this is purely an aggregated value, so only offer-up the options to the end-user that make sense here. For the same textual field we now don't see the option to summarise, e.g.:

        The doc is not 100% correct on this, and specifies Measure is for numeric values. I might have to figure out how to submit corrections to see if this can be cleared up.

        So with that in mind, don't think of Measure as a data model measure, more that "this data role should aggregate however it can, based on its type". For numeric values, you'll get the standard numeric ones such as min, max etc.; for textual fields we get the ones above. This is how the circle card tutorial is set up, and also how the core card visual works when you add textual fields to them.

        My Approach for your Visual

        When you want to use multiple data roles, this is where we can get creative with the categorical dataViewMapping. We don't have to specify a categories grouping as long as there's a valid binding to values, so I would firstly revise the dataRoles for your case as follows:

        "dataRoles": [
            {
                "displayName": "Station ID",
                "name": "stationID",
                "kind": "Measure"
            },
            {
                "displayName": "Throughput",
                "name": "throughput",
                "kind": "Measure"
            },
            {
                "displayName": "Status",
                "name": "status",
                "kind": "Measure"
            },
            {
                "displayName": "Color",
                "name": "color",
                "kind": "Measure"
            }
        ],

        I'd then set up my dataViewMappings as follows:

        "dataViewMappings": [
            {
                "categorical": {
                    "values": {
                        "select": [
                            {
                                "bind": {
                                    "to": "stationID"
                                }
                            },
                            {
                                "bind": {
                                    "to": "throughput"
                                }
                            },
                            {
                                "bind": {
                                    "to": "status"
                                }
                            },
                            {
                                "bind": {
                                    "to": "color"
                                }
                            }
                        ]
                    }
                }
            }
        ]

        Note that I'm not using a categories key, just a values one (as I don't need to be doing any grouping for a "single" data point).

        Now, when I refresh my visual and add my data, the dataView will now resolve as follows:

        I'm just using whatever data I have in my model but yours should resolve similarly. Notice that everything is consolidated in the values object.

        In terms of how you then access in your code thereafter, you'd swap out any instances of where you're referring to the categories object (e,g, for stationText and stationValue) and map them to the appropriate entry in the values object array instead.

        Let me know if there's anything in here that doesn't make sense and I'll do my best to provide more targeted feedback 😉

        Good luck!

        Daniel