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

Pop up window (face plate)


  • Thanks, that would be great. Don't go to too much trouble on it. :)


  • OK!
    As a starting point to work from. I'll work with you so you learn how it all works as you go...
    (All code is placed in the /opt/mango/overrides/web... directories)
    /modules/mangoUI/web/dev/components/settingsModal.js

    define(['angular', 'require'], function(angular, require) {
    'use strict';
    
    /* Date: 1/9/18
    	   Author: Matt "Fox" Fox
    	   Desc: component written to launch a modal dialog with either a built in template or just spit out a list of points to save one by one.
    	*/
    	settingsModalController.$inject = ['$mdDialog','maJsonStore'];
    		function settingsModalController ($mdDialog,maJsonStore)
    		{
    			var ctrl = this;
    			ctrl.mdDialog = $mdDialog;
    			ctrl.parsedOptions=[];
    			
    			ctrl.values={};
    			
    			this.$onInit = function()
    			{
    				if(this.points && !angular.isArray(this.points))
    				{
    					console.log('Error: points field not an array of point objects');
    				}
    				if(this.pointOptions && !angular.isArray(this.pointOptions) )
    				{
    					console.log('Error: points options field not an array');
    				}
    				ctrl.clickOffClose = ctrl.clickOffClose===true?true:false;
    				
    				
    				
    				
    				
    			};
    			
    			this.$onChanges = function(e)
    			{
    				console.log(e);
    				checkPoints();
    			}
    			
    			function checkPoints()
    			{
    				ctrl.parsedOptions=[];
    				if(ctrl.points && angular.isArray(ctrl.points))
    				{
    					if(ctrl.pointOptions && angular.isArray(ctrl.pointOptions) )
    					{
    						var ptName,ptDesc;
    						for(var i=0; i<ctrl.points.length; i++)
    						{
    							ptName=ctrl.points[ i ].name;
    							ptDesc='';
    							if(ctrl.pointOptions[ i ] && ctrl.pointOptions[ i ].hasOwnProperty('name') )
    							{
    								ptName = ctrl.pointOptions[ i ].name;
    							}
    							if(ctrl.pointOptions[ i ] && ctrl.pointOptions[ i ].hasOwnProperty('desc') )
    							{
    								ptDesc = ctrl.pointOptions[ i ].desc;
    							}
    							ctrl.parsedOptions.push( {name:ptName,desc:ptDesc} );
    						}
    					}
    					else
    					{
    						for(var i=0; i<ctrl.points.length; i++)
    						{
    							ptName=ctrl.points[ i ].name;
    							ptDesc='';
    						
    							ctrl.parsedOptions.push( {name:ptName,desc:ptDesc} );
    						}
    					}
    				}
    				else if(ctrl.pointOptions && angular.isArray(ctrl.pointOptions) && !ctrl.points )
    				{	
    					var ptId, ptName, ptDesc;
    					for(var i=0; i<ctrl.pointOptions.length; i++)
    					{
    						if(ctrl.pointOptions[ i ] && !ctrl.pointOptions[ i ].hasOwnProperty('name') )
    						{
    							// ctrl.pointOptions=[];
    							ctrl.parsedOptions=[];
    							return;
    						}
    						ptId=i;
    						ptDesc='';
    						ptName=ctrl.pointOptions[ i ].name;
    						if(ctrl.pointOptions[ i ] && ctrl.pointOptions[ i ].hasOwnProperty('id') )
    						{
    							ptId = ctrl.pointOptions[ i ].id;
    						}
    						if(ctrl.pointOptions[ i ] && ctrl.pointOptions[ i ].hasOwnProperty('desc') )
    						{
    							ptDesc = ctrl.pointOptions[ i ].desc;
    						}						
    						ctrl.parsedOptions.push( {id:ptId,name:ptName,desc:ptDesc} );
    					}
    				}
    			}
    			
    			/* DIALOG CODE */
    			ctrl.showDialogue = function(ev) {
    			   // ctrl.updateModals();
    			   if( ctrl.altTemplateUrl!==undefined  )
    			   {
    				   try
    				   {
    					   
    					ctrl.mdDialog.show({
    					  templateUrl:ctrl.altTemplateUrl, 
    					  parent: angular.element(document.body),
    					  targetEvent: ev,
    					  clickOutsideToClose: ctrl.clickOffClose
    					}).then(
    						function()
    						{
    							console.log('function if closed/hidden manually'); 
    						},
    						function()
    						{
    							console.log('function to fire if closed from clicking outside/cancelled');
    						}
    					);
    				   }catch(e){console.warn(e);}
    			   }
    			   else
    			   {
    				   try{
    					   
    					ctrl.mdDialog.show({
    					  contentElement: '#settingsModal',
    					  parent: angular.element(document.body),
    					  targetEvent: ev,
    					  clickOutsideToClose: ctrl.clickOffClose
    					}).then(
    						function()
    						{
    							console.log('function if closed manually'); 
    						},
    						function()
    						{
    							console.log('function to fire if closed from clicking outside/cancelled');
    						}
    					);
    				   }catch(e){console.warn(e);}
    				}
    			};
    			
    			ctrl.hideDialogue = function() {
    				ctrl.mdDialog.hide();
    			};
    
    			ctrl.cancel = function() {	  
    				ctrl.mdDialog.cancel();
    			};
    			/* DIALOG CODE END*/
    			
    			/* JSON Store Stuff: */
    			ctrl.saveToStore = function(data=null)
    			{
    				
    				var item = maJsonStore.newItem( ctrl.jsonStore.toLowerCase() );
    				item.jsonData = data===null ? ctrl.values : data;
    				item.readPermission= "user";
    				item.editPermission= "user"; //can change this at your leisure or we can break it out into a setting...
    				
    				var r = item.$save();
    				
    				if(r.status)
    				{ 
    				}
    				else
    				{ 
    				}
    			};
    			
    			ctrl.loadFromStore = function()
    			{
    				maJsonStore.get({xid: ctrl.jsonStore.toLowerCase() }).$promise.then(function(item) {
    				ctrl.values = item.jsonData;
    			});
    			/* JSON Store Stuff END: */
    			};
    			
    			/* Virtual Point Save stuff */
    			ctrl.saveToPoint = function()
    			{
    				if(ctrl.savePoint===undefined)
    				{
    					alert('Point to save to not set as attribute!');
    					return;
    				}
    				ctrl.savePoint.setValue( JSON.stringify(ctrl.values) );
    			};	
    			
    			/* Virtual Point Save stuff END */
    	}
    		
    		
    		
    	
    	var settingsModal={
    		bindings:{
    			jsonStore: '<?', 		//Store name to save settings to
    			savePoint: '<?', 		//alternatively, save my JSON to a virtual pt, MUST BE TYPE DATAPOINT...
    			altTemplateUrl:'=?', 	//If we want to use the popup to show something else: use this template...
    			modalTitle:'=?', 		//seemed like a good idea at the time... will only work if altTemplateUrl is empty
    			clickOffClose:'=?', 	//set to true to click outside modal to shut it
    			pointOptions:'<?', 	//Alternate names for points,  (object array) [{id:'',name:'',desc:''}], id used for key name if using json/virtual point save
    			points: '<?',			 //Array of points to set individually
    		},
    		controller: settingsModalController,
    		templateUrl:'/modules/mangoUI/web/dev/views/modalDemo.html'
    	};
    	
    	return settingsModal;
    });
    

    and the template markup to add:
    /modules/mangoUI/web/dev/views/modalDemo.html

     <ma-button  hue="hue-2" palette="primary" label="Open Dialogue" ng-click="$ctrl.showDialogue()" raised="true"></ma-button>
     <div ng-if="!$ctrl.altTemplateUrl" style="visibility: hidden">
        <div class="md-dialog-container" id="settingsModal">
          <md-dialog layout-padding>
    			<md-dialog-actions><md-button ng-if="!$ctrl.clickOffClose" ng-click="$ctrl.cancel()" class="md-primary">x</md-button></md-dialog-actions>
     <div ng-if="!$ctrl.points && !$ctrl.parsedOptions">
    		Custom markup needed!
    		</div>
    		 
           <h1 ng-if="$ctrl.modalTitle!==undefined">{{$ctrl.modalTitle}}</h1> <small ng-if="$ctrl.clickOffClose">Click outside dialogue to close</small>
    		
    		<div ng-if="$ctrl.points">
    		<md-input-container ng-repeat="(index,point) in $ctrl.points" style="display:block;width:100%;">
    	   {{$ctrl.parsedOptions[index].name}}
    			<br/>	
    	   {{$ctrl.parsedOptions[index].desc}}
    			<br/>	
    			
    		<span style="display:inline-block;">Current Value: <ma-point-value style="display:inline-block;" point="point" ></ma-point-value></span>
    		 <ma-set-point-value  point="point" show-button="true"></ma-set-point-value> 
    		</md-input-container>
    		</div>
    		<div ng-if="!$ctrl.points && $ctrl.parsedOptions.length>0">
    			<md-input-container ng-repeat="input in $ctrl.parsedOptions">
    			{{input.name}}<br/>{{input.desc}}
    			<input ng-model="$ctrl.values[ input.id ]"/>
    			</md-input-container>
    		</div>
    		
          </md-dialog>
        </div>
      </div>
    

    More than happy to help you work through this (it will be a bit of a crash course)
    I've not added the buttons on the template for saving using a virtual point or JSON store, but that can be added quite easily.
    Basically you can generate a popup which will populate with inputs that can be named, given an ID and a description if necessary. This can also be used to override point names to more 'user friendly' equivalents for your users if they're filling out items in the dialogue box.

    inside the userModule.js directory (assuming that's the name of the file you've followed from Jared's tutorial) you'll want this structure:

    /userModule.js
    /components/settingsModal.js
    /views/modalDemo.html

    and inside userModule.js you'll want this:

    define(['angular', 'require','./components/settingsModal.js'], function(angular, require,settingsModal) {
        'use strict';
     var userModule = angular.module('userModule', ['maUiApp']);
    try {	
    	userModule.component('settingsModal', settingsModal);
    }
    catch(e){console.log(e);}	
        return userModule;
    });
    

    Markup in the dashboard page builder will be:

    <settings-modal point-options="[{id:'test',name:'input 1',desc:'input test 1'},{id:'test2',name:'input 2',desc:'input test 2'}]" points="vp" click-off-close="true"></settings-modal>
    

    See if you can get the popup showing for you first. I'm using 3.4.1 so I'm not completely sure if this will be affected in your version of mangoUI...

    Fox

    EDIT: sorry I'll be sure to add some more code comments later...
    New Edit: added data to save to store as an optional argument


  • For anyone following this thread:
    found a small typo on the useModule.js code. The try block needs to be closed with a }.

    @MattFox Thank you very much for doing this. I've been wanting to dive into modules for sometime now but have never been able to find the time. This will really help with the learning curve.

    There is just one thing that has got me here. When I try add a 2nd userModule my previous one disappears. Could someone help me with how to do this correctly, it will be very much appreciated.


  • Thanks regarding the typo, I'll take a look and will correct it.
    As for your user module. You only have one. You append all of your components and controllers to it.
    I use a try catch to see where it fails. if you wrap them around each module then you can successfully determine how things are failing without breaking the entire module and losing all of your components/controllers...
    Happy to take a look for you. Otherwise feel free to private message me, same goes for Ian and Joey.

    EDIT:have corrected by adding missing brace


  • @MattFox Thanks for that tip, I edit the userModule.js like this to add a second module. don't get any console errors.

    define(['angular', 'require','./components/settingsModal.js'], function(angular, require,settingsModal) {
        'use strict';
     var userModule = angular.module('userModule', ['maUiApp']);
    try {	
    	userModule.component('settingsModal', settingsModal);
        }
    catch(e){console.log(e);}	
    
    try{userModule.component('myComponent', {
        bindings: {
            name: '@?'
        },
        template: '<span>Hello {{$ctrl.name}}</span>'
    });
    }
    catch(e){console.log(e);}
    
        return userModule;
    });
    

  • Well if there is nothing being printed in the console, that's a sign of something working....
    Do note that console.log() outputs as an informative text. If you're using chrome, ensure under the console for default levels that it's ticked:
    0_1536033304366_69b04a4b-7b42-4aae-95a8-6b49c32ada99-image.png

    Secondly, check on the page you have myComponent on and check the console there to ensure there is not some silly form of a clash etc...

    Fox


  • Thanks Matt, I was able to get your example working. Now to play around with retrieving and saving data to a data point or JSON store.

    One thing that confused me was the folder structure that was required. I followed the (Jared's) tutorial that you linked which created the userModule.js in /rest/v2/file-stores/public/userModule.js. You mentioned that within this directory I need to create:
    /components/settingsModal.js
    /views/modalDemo.html

    Also, you mentioned creating these directories and files under: /mango/overrides/web/modules/mangoUI/web/dev/

    It seemed odd that the files would (appear to) be duplicated in these 2 locations.

    What I found to work was that the settingsModal.js was located in:
    /rest/v2/file-stores/public/components/settingsModal.js (based on the path defined in the userModal.js)
    and the modalDemo.html was located in:
    /mango/overrides/web/modules/mangoUI/web/dev/views/modalDemo.html (based on the path defined in settingsModal.js)

    Is this correct? It would seem to be bit of a maintenance pain to have the files located in different contexts.

    This example was great. Thanks again

    Ian


  • So sorry Ian, didn't mean to perplex you.
    I store all of my files in /opt/mango/overrides/web/modules/mangoUI/web/dev directories.
    0_1536107492653_afcae342-46ab-4138-9e67-6038b10693e4-image.png
    This way I don't need to concern myself with changes or being overwritten with mango updates.

    So by this I mean userModule.js is
    /opt/mango/overrides/web/modules/mangoUI/web/dev/userModule.js

    the modalDemo.html:
    /opt/mango/overrides/web/modules/mangoUI/web/dev/views/modalDemo.html

    and the settingsModal.js file is in
    /opt/mango/overrides/web/modules/mangoUI/web/dev/components/settingsModal.js

    The reason I do this is to better segment my code. You can put it all in one directory if you'd rather, but as I have done a lot of MVC programming in my PHP days I'm used to separating my model, controller and views for consistency.

    @iperry said in Pop up window (face plate):

    Now to play around with retrieving and saving data to a data point or JSON store.

    If you look under the settingsModal.js I've done some code for you to do that.
    Just add a button to the view and call the method with $ctrl.saveToStore( ) or for a virtual point,
    make sure you simply set your virtual point in the savePoint attribute and call the. $ctrl.saveToPoint() method.

    Hmm, should remove that (data) argument for the JSON store method...

    Anyway! Once you've got that saving we can look at loading the data and re-populating your fields.


  • Ahh, thanks. I wasn't sure if you could specify where the userModule.js was other than from the public store. I would rather use the overrides directory(s) for my code so I will change the path. I had tried to use this directory before but didn't get the path from the ui quite right.

    I like the way you segment your code. I have been working with a few MVC frameworks over the years as it fits well with the way I code. Sometimes can be fun trying to trace through code but the modularity is great.

    I saw your segments for interfacing with the json store and data points. Those are my next stop in this trip. :)

    Ian


  • For anyone that finds this thread, you can create a dialog window in Mango 3.6 very easily -

    <ma-button label="Show dialog" ng-click="showDialog = {}"></ma-button>
    
    <ma-dialog show-dialog="showDialog">
        <div>This is the dialog content</div>
    </ma-dialog>