• Recent
    • Tags
    • Popular
    • Register
    • Login

    Please Note This forum exists for community support for the Mango product family and the Radix IoT Platform. Although Radix IoT employees participate in this forum from time to time, there is no guarantee of a response to anything posted here, nor can Radix IoT, LLC guarantee the accuracy of any information expressed or conveyed. Specific project questions from customers with active support contracts are asked to send requests to support@radixiot.com.

    Radix IoT Website Mango 3 Documentation Website Mango 4 Documentation Website Mango 5 Documentation Website

    Styling a Custom Component in userModule

    Dashboard Designer & Custom AngularJS Pages
    4
    17
    4.8k
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • MattFoxM
      MattFox
      last edited by

      Here's something to get you started, I'm not sure what the purpose of the ng-click is for your image, if you are able to explain i'll likely be able to assist with that part.
      I am not sure what name and face are for either.
      Basically with the component, you're bringing all of the dynamic variables to the surface as bindings for the component. From here you do all of your calcs and fancy doodads inside the component's controller.

      Your html:

      <section>
      <style>
      .idle { background-color: rgba( 255, 255, 255, 0.5); }
      .heat { background-color: rgba( 255, 255, 0, 0.5 ); }
      .air { background-color: rgba( 3, 186, 252, 0.5 ); }
      .heatair { background-image: url("/rest/v2/file-stores/default/HeatAir.png"); }
      .a0 { background-image: url("/rest/v2/file-stores/default/A0.png"); }
      .s1 { background-image: url("/rest/v2/file-stores/default/Stage1.png"); }
      .s2 { background-image: url("/rest/v2/file-stores/default/Stage2.png"); }
      .s3 { background-image: url("/rest/v2/file-stores/default/Stage3.png"); }
      .manual { background-color: rgba( 0, 0, 0, 0.5); }
      </style>
      <ma-get-point-value point="sequence1" point-xid="{{$ctrl.pointXid}}"></ma-get-point-value>
      <!-- ng-click="designer.parameters = {dn: 'sg-lsb-01v'}" What is this for?? -->
      <img id="{{$ctrl.pointXid}}_img" style="width: 30px; height: 28px;" src="/rest/v2/file-stores/default/HKDStickL.png" ng-click="designer.parameters = {dn: 'sg-lsb-01v'}" ng-class="{0:'idle', 1:'heat', 2:'air', 3:'heatair', 4:'a0', 5:'s1', 6:'s2', 7:'s3', 8:'manual'} [sequence1.value]">
      </section>
      

      Your component

      userModule.component('stickGun', {
          bindings: {
              name: '>?',  //1-way binding optional
              face: '>?',
      		pointXid:'>' //required
          },
          templateUrl: '/rest/v2/file-stores/public/stickGun.html',
          styleUrls: ['/rest/v2/file-stores/public/userModule.css'], //not hugely needed, especically if you use the user styles file to store all your css in. Unless you plan to take this component to other places...
      	controller:function(){
      		var ctrl = this;
      		this.$onChanges = function(e)
      		{
      			//binding checks are done in here. this is for an example of what I stated prior if you are using optional bindings
      			if(e.pointXid && e.pointXid.currentValue!=undefined)
      			{
      				ctrl.pointXid = e.pointXid.currentValue;
      			}
      		};
      		
      	}
      });
      

      Do not follow where the path may lead; go instead where there is no path.
      And leave a trail - Muriel Strode

      P 1 Reply Last reply Reply Quote 1
      • P
        pyeager @MattFox
        last edited by

        @mattfox Thanks!

        It's quitting time. so I'll play with it tomorrow.

        When the image is clicked, ng-click set which device's details are shown on a card.

        1 Reply Last reply Reply Quote 0
        • Jared WiltshireJ
          Jared Wiltshire
          last edited by

          @pyeager This is what I would do, based off your code. Note that styleUrls seems to be Angular 2+ syntax, not AngularJS (1.x). Put your CSS in the user styles style sheet (under UI settings).

          User module -

          define(['angular', 'require'], function(angular, require) {
          'use strict';
          
          var userModule = angular.module('userModule', ['maUiApp']);
          
          // doesn't do anything, but here for completeness
          class StickGunController {
          }
          
          userModule.component('stickGun', {
              bindings: {
                  name: '@?', // dont know what these are for, but sure
                  face: '@?',
                  point: '<?'
              },
              templateUrl: '/rest/v2/file-stores/public/stickGun.html',
              controller: StickGunController
          });
          
          return userModule;
          
          }); // define
          

          Template file (/rest/v2/file-stores/public/stickGun.html) -

          <ma-get-point-value point="$ctrl.point"></ma-get-point-value>
          <img src="/rest/v2/file-stores/default/HKDStickL.png" ng-class="{0:'idle', 1:'heat', 2:'air', 3:'heatair', 4:'a0', 5:'s1', 6:'s2', 7:'s3', 8:'manual'}[$ctrl.point.value]">
          

          CSS file -

          stick-gun {
              display: block;
          }
          stick-gun > img {
              width: 100%;
              height: 100%;
          }
          stick-gun > img.idle { background-color: rgba( 255, 255, 255, 0.5); }
          stick-gun > img.heat { background-color: rgba( 255, 255, 0, 0.5 ); }
          stick-gun > img.air { background-color: rgba( 3, 186, 252, 0.5 ); }
          stick-gun > img.heatair { background-image: url("/rest/v2/file-stores/default/HeatAir.png"); }
          stick-gun > img.a0 { background-image: url("/rest/v2/file-stores/default/A0.png"); }
          stick-gun > img.s1 { background-image: url("/rest/v2/file-stores/default/Stage1.png"); }
          stick-gun > img.s2 { background-image: url("/rest/v2/file-stores/default/Stage2.png"); }
          stick-gun > img.s3 { background-image: url("/rest/v2/file-stores/default/Stage3.png"); }
          stick-gun > img.manual { background-color: rgba( 0, 0, 0, 0.5); }
          

          Developer at Radix IoT

          1 Reply Last reply Reply Quote 0
          • Jared WiltshireJ
            Jared Wiltshire
            last edited by

            Oh, and to use, you just add this to your page -

            <stick-gun point="myPoint"></stick-gun>
            

            Developer at Radix IoT

            1 Reply Last reply Reply Quote 0
            • MattFoxM
              MattFox
              last edited by

              Thanks Jared, appreciate the support!

              Do not follow where the path may lead; go instead where there is no path.
              And leave a trail - Muriel Strode

              1 Reply Last reply Reply Quote 0
              • P
                pyeager
                last edited by

                Thank you both for your help.

                I might need just a little more.

                Specifying a data point by xid, as both of your examples do, is a bit less than optimal for a couple of reasons.

                For one thing, there are multiple data points with which the component needs to interact.

                Also, specifying one or more data points by xid is less than user friendly. My preferred approach is to just name the component instance in such a way that queries can be constructed from the instance name, removing the need to specify an xid for each data point.

                ...and additionally...

                This may be asking a lot, but ideally adding this component to a dashboard would also create a few data sources, likely from a template. That would make the drag and drop addition of the component and definition of element-specific details pretty much all that is necessary to add a machine to the system.

                Jared WiltshireJ MattFoxM 2 Replies Last reply Reply Quote 0
                • Jared WiltshireJ
                  Jared Wiltshire @pyeager
                  last edited by

                  @pyeager said in Styling a Custom Component in userModule:

                  Specifying a data point by xid, as both of your examples do, is a bit less than optimal for a couple of reasons.

                  My example does not specify a data point by XID, it passes a single data point through.

                  @pyeager said in Styling a Custom Component in userModule:

                  For one thing, there are multiple data points with which the component needs to interact.

                  In this case you could pass a whole array of data points through (from a query or Watchlist) and filter the points out inside the component.

                  @pyeager said in Styling a Custom Component in userModule:

                  Also, specifying one or more data points by xid is less than user friendly. My preferred approach is to just name the component instance in such a way that queries can be constructed from the instance name, removing the need to specify an xid for each data point.

                  I agree you should not directly bind components to a specify XID. This is why our dashboard designer supports selecting a watchlist then binding components to data points using their name.

                  If you want to use a name attribute for your components this would work in a similar fashion. Like I said above, pass the whole points array through to the component and then find the point you want inside the component using the name attribute.

                  e.g. controller for your component

                  class StickGunController {
                    $onChanges(changes) {
                      if (changes.points && Array.isArray(this.points)) {
                        this.point = this.points.find(pt => pt.name === this.name);
                      }
                    }
                  }
                  

                  @pyeager said in Styling a Custom Component in userModule:

                  This may be asking a lot, but ideally adding this component to a dashboard would also create a few data sources, likely from a template. That would make the drag and drop addition of the component and definition of element-specific details pretty much all that is necessary to add a machine to the system.

                  Certainly possible, I don't have time to get right into this right now but you could use the maDataSource service to check for the existence of the DS and create it if one matching the name attribute doesn't exist.

                  Developer at Radix IoT

                  P 1 Reply Last reply Reply Quote 1
                  • P
                    pyeager @Jared Wiltshire
                    last edited by

                    @jared-wiltshire said in Styling a Custom Component in userModule:

                    Like I said above, pass the whole points array through to the component and then find the point you want inside the component using the name attribute.

                    How does one pass the whole points array to the component?

                    Jared WiltshireJ 1 Reply Last reply Reply Quote 0
                    • phildunlapP
                      phildunlap
                      last edited by

                      By defining "points" as an input of the component, as I did in this post: https://forum.infiniteautomation.com/topic/3503/how-to-chart-with-data-points-in-the-x-axis-instead-of-time/6

                      1 Reply Last reply Reply Quote 0
                      • Jared WiltshireJ
                        Jared Wiltshire @pyeager
                        last edited by

                        @pyeager said in Styling a Custom Component in userModule:

                        How does one pass the whole points array to the component?

                        Are you asking how to define the binding in the component or how to pass the points to the attribute when you are using it?

                        To define the binding, you literally just have to change point to points in the example I posted above. I gave you a controller that will locate the point from the array using the name attribute.

                        If you meant the latter, I suggest you peruse the examples that are built into Mango (enable the examples menu item using the menu editor if you have not already).

                        Developer at Radix IoT

                        1 Reply Last reply Reply Quote 0
                        • MattFoxM
                          MattFox @pyeager
                          last edited by

                          @pyeager said in Styling a Custom Component in userModule:

                          For one thing, there are multiple data points with which the component needs to interact.

                          You never stated this initially

                          @jared-wiltshire said in Styling a Custom Component in userModule:

                          Certainly possible, I don't have time to get right into this right now but you could use the maDataSource service to check for the existence of the DS and create it if one matching the name attribute doesn't exist.

                          If this is remotely similar to making a new point using the maPoint service perhaps I can be of assistance here

                          Do not follow where the path may lead; go instead where there is no path.
                          And leave a trail - Muriel Strode

                          1 Reply Last reply Reply Quote 1
                          • First post
                            Last post