Page Components

From Dreamtsoft Wiki
Jump to: navigation, search

Overview

Dreamtsoft page components serve as the data display mechanism on the UI. Every page in Dreamtsoft will contain 1-n number of page components, all of which will display the data provided from the Data Service. Whether using our out of the box page components, or creating your own, this article will walk you through their use. For reference, the following image contains eight (8) page components, seven (7) Charts and one (1) Static HTML component (to display the round image in the middle).

Out of box page components

See Component Examples

Understanding and creating page components

You can create your own page components in Dreamtsoft! Not being restricted to our published page components is one of the major differentiators that makes the Dreamtsoft platform so powerful!

Video

Overview

Page variables are arbitrary variables in the URL that components listen to when changes occur and update their own values when an event happens.

Page vars.png

Creating Page Variables

Admins have the ability to create their own custom page variables that can drive changes in components.

Pvar1.png

From the layout editor select the page to take you to the edit page screen.

Pvar2.png

Click the branch icon in the bottom left of the edit page screen to display the existing page variables.

Pvar3.png


File Structure

A very specific structure is required for uploading a new component into your bundle. The structure looks like you see below. This is a screenshot of an implementation of the FullCalendar library into a "calendar" component in Dreamtsoft. Note that the "components" folder needs to go into the root folder of your bundle.

Component folder structure.png

ComponentNameClient.html

Your client document (in our example: ImageSliderClient.html) will contain all of the following sections:

Definition

This is how the system identifies your component

<definition>
{
  id:"image_slider",
  label:"Image Slider",
  className:"ImageSliderServer",
  renderable:"true"
}
</definition>
  • id - the unique name of the component
  • label - the pretty name of the component, that'll be displayed to the admins of the tool when dragging your component into a page
  • className - the name of the Server file (see below). Usually formatted like "ComponentNameServer"
  • renderable - determines whether the component is selectable from the components menu

Attributes

These are the slots that show up when configuring your component, and end up being available to both the client and server scripts by referencing "attributes.attributeName"

<attributes>
[
	{
		name: "bucket",
		label: "Bucket",
		type: "choice",
		attributes: {
			"choice_type": "dropdown",
			"buckets": "true",
			"none_option": "true"
		}
	},{
		name: "suffix",
		label: "Suffix",
		type: "choice",
		attributes: {
                       "choice_type": "dropdown",
                       "default": "png",
                       "choices": [
					{ label: 'All images', value: 'all' },
					{ label: 'PNG', value: 'png' },
					{ label: 'JPG', value: 'jpg' },
					{ label: 'GIF', value: 'gif' },
			]
		}
	}
]
</attributes>

Attributes Layout

This controls how the attributes listed above display on the screen. This is basically building the detail layout for the screen.

<attributes_layout>
	[ "bucket", "suffix" ]
</attributes_layout>

Attributes Display Rules

These display rules can hide, make readonly, and make mandatory your attributes (defined above) based on conditions. The following two rules make the "Bucket" attribute mandatory always, and the "Suffix" attribute hidden when the bucket is empty

<attributes_display_rules>
[
	{
		"slot": "bucket",
		"conditions": {
			"mandatory": []
		}
	},{
		"slot": "suffix",
		"conditions": {
			"hidden": ["bucket","eq",""]
		}
	}
]
</attributes_display_rules>


Style

The style section allows for CSS to be placed in your code that'll help style your elements

<style>
    .image_viewer {
        width: 100%;
        height: 500px;
    }
</style>

Script

The script section will contain most of the "meat" of your UI implementation. This is where you'll define specific functions that tell the component how to render, display, and act.

<script>
	exports.component = ComponentUI.create({
		onRender: function(container, data, attributes) {
			var w = container.width();
			var h = container.height() || 400;
			this.id = 'uniqueImageSliderID' + Client.guid();
 			var primaryDiv = $('<div id="' + this.id + '"></div>');

			for(var i = 0; i < data.urls.length; i++) {
				var urlVar = data.urls[i];
				primaryDiv.append('<img src="' + urlVar + '" alt="">');
			}

			container.append(primaryDiv);

			this.slider = new IdealImageSlider.Slider('#' + this.id);
			this.slider.addBulletNav();
			this.slider.start();
			
		},

		onUnloaded: function() {
			this.slider.destroy();
			this.slider = undefined;
		},

		className: "ImageSliderClient"
	});
</script>

Server Code

The server code will do all of the "backend" work, generally used to lookup data and return values used by the client side

var PageComponent = require("ds.base/PageComponent");

var ImageSliderServer = PageComponent.create({
	data: function(attributes, vars, containerList) {
		var urlArray = [];

		//Search for all upload records
		var fr = new FRecord('upload');
		fr.search();
		while (fr.next()) {
			//Check to see if we need to match a suffix
			if (attributes.suffix != 'all') {
				//Check to see if the suffix matches
				if (fr.name.indexOf(attributes.suffix) >= 0) {
					//Add the url to the list
					urlArray.push(fr.url);
 				}
			} else {
				//Pushing all urls
				urlArray.push(fr.url);
			}		
		}
		
		return new StatusResponse('good', {
			urls: urlArray
		});
	},
	
	type: "ImageSliderServer"
});

module.exports = ImageSliderServer;

AJAX Calls

The following example calls the AJAX function testEvent located in the TestServer.js file in the test_client component folder.

This example demonstrates both how to return data onLoad and replace data in the HTML as well as how to initiate an AJAX call after the initial load (button click)


Example TestClient.html

 
<!DOCTYPE f8component>

<definition>
	{
	id: "test_client",
	label: "Test",
	className: "TestServer",
	renderable: true
	}
</definition>

<template name="test.container">
	<div class="kbContainer">
		<h2 id=demo><%= JSON.stringify(data) %></h2>
			<button onclick="myFunction()">Click me</button>

			</div>
		<script>
			function myFunction() {
				document.getElementById("demo").style.color = "red";
				new Component('test_client').ajax('testEvent', {
					bucketName: "Donovans Bucket",
					recordId: "Donovans ID"
				}, {
					callback: $.proxy(function(response) {
						if (response && response.status == 'good') {
							var data = response.data;
							console.log("Return DATA " + JSON.stringify(data));
						} else {
							Client.alert('Error: ' + response.status_message);
						}
					}, this),
					error: function() {
						Client.alert('Error responding to approval');
					}
				});
			}
		</script>
		</template>

	<script>
		exports.component = ComponentUI.create({
			onLoad: function(data) {
				this.template('test.container', this.container, data, this.attributes);
			},

			className: "testServer"
		});
	</script>


Example TestServer.js

var PageComponent = require("ds.base/PageComponent");

module.exports = PageComponent.create({
	"/": function(attributes, vars) {		
		
		return new StatusResponse('good',{name:"Colin"});		
	},
	
	"/ajax/testEvent": function(vars) {
		var title = "Donovan's Title";
		var bucketName = vars.bucketName;
		var bucketId = vars.bucketId;
		console.log("Server VARS " + JSON.stringify(vars));
		
		//Create the record
		//var r = new FRecord(bucketName);
		//r[titleSlot] = title;
		//r.insert();

		var returnObject = {name: "DonovanReturnObj"};

		return new StatusResponse('good', {
			returnObject: returnObject
		});
	},
});