EnyoJS Tutorial #6 – Loading Data to Form

Today’s tutorial is the follow up tutorial for previous tutorial part #5. We will be using the resources from previous tutorial part 5 to continue. In this tutorial we are going to cover the followings :-

  • How to load a value of picker dynamically (this is useful when we want to populate values of the picker content from server side or some local settings file.)
  • Loading an internal JSON text file using AJAX.
  • How to destroy previous controls and render new component into picker. (very important).
  • How to search and setSelected value of the picker based on previously stored value.
  • setValue to all the form inputs and textarea.

First, we start with retrieving a local JSON file using AJAX. The content of the JSON file is stored in asset folder, which contains the follow JSON schema. We are going to load it using AJAX.  See code below on the sample JSON file called, membertype.json.

For now, just create this file with the codes below and save it as a flat text file called membertype.json. In actual development, sometimes we store settings file in this format, such as ajax’s default server gateway, port and etc.

{
    "membertype":[
        {content:"Platinum"},
        {content:"Gold"},
        {content:"Silver"}
    ]
}

Next, let’s modify SampleForm.js from previous tutorial, to load membertype.json using AJAX, then push it into the picker control. To do that, we will also need to erase the components portion of the picker because, it will be loaded dynamically.

The logic flow we going to implement is this…

  • onCreate of SampleForm, we load data from file membertype.json right into memory.
  • clear any previous component attached into picker. Push the json structure into picker as component.
  • render the picker’s list.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
enyo.kind({
	name: "SampleForm",
	kind: "FittableRows", 
	classes: "enyo-fit enyo-unselectable padding15px formBg",
	components: [
		{ style:"height:20px" },
		{   
			kind: "onyx.InputDecorator",
			classes:"inputStyler", 
			components: [
				{
					name:"txtName", 
					kind: "onyx.Input", 
					placeholder: "Enter a Name",
					type:"text",
					attributes:{
						maxlength:80,
						required:"required"				
					}
				}
			] 	
		},
		{ style:"height:10px" },
		{   
			kind: "onyx.InputDecorator",
			classes:"inputStyler", 
			components: [
				{
					name:"txtPassword", 
					kind: "onyx.Input", 
					placeholder: "Enter Password",
					type:"password",
					attributes:{
						maxlength:10,
						required:"required"				
					}  
				}
			] 	
		},
		{ style:"height:10px" },
		{
			layoutKind: "FittableColumnsLayout",
			style:'height:32px',
			components:[
				{ 
					content:"Registered Member ? ",
					style:"width:200px;padding:8px;"
				},
				{
					name:"checkMember",
					kind:"onyx.Checkbox", 
					onchange:"checkboxChanged", 
					checked: true,
					style:"width:100px;"
				}
			]
		},
		{ style:"height:10px" },
		{
			name:"pickerMemberType",
			kind: "onyx.PickerDecorator", 
			components: [
				{
					kind: "onyx.PickerButton", 
					content: "Select Member Type...", 
					style: "width: 100%"
				},
				{
					// Notice, I deleted the components attributes with all it's child data.
					// Given the control a name to assign components into it.
					name:"memberTypePicker",
					kind: "onyx.Picker"
				}
			]
		},
		{ style:"height:10px" },
		{   
			kind: "onyx.InputDecorator",
			classes:"inputStyler", 
			components:[
				{
					kind:"onyx.TextArea",
					name:"txtAddress",
					style:'width:100%',
					placeholder:"Enter Address",
					attributes:{
						maxlength:300,
						required:"required"				
					} 
				}
			] 
		}  		
	],
	create: function(inSender,inEvent){
		this.inherited(arguments);
		this.loadDataForMemberType();
	},
	loadTextFile:function(url,onSuccess,onError){
		// A simple ajax called that have two callbacks as parameter.
		// returns itself back to the caller. 
		var ajaxGet =  new enyo.Ajax({
			url:url,
			method:'GET',
			handleAs:'json'
		});	
		ajaxGet.go();
		ajaxGet.response(this, onSuccess);
		ajaxGet.error(this, onError);
	},
 
	loadDataForMemberType:function(){
		var self = this;
		console.log("Loading data from membertype.json...");
		this.loadTextFile("assets/membertype.json",onSuccess,onError);
		function onSuccess(inSender,inResponse){
			// Take note whenever you are dealing with subfunction, "this" context may differ 
			// based on it's own closure. Best to assigned "this" to another variable. See line 112.
			// According to API documentation enyo.Ajax function always returns inSender, inResponse.
			// calling this.<functioname> here will result in error, so use self instead.
			console.log(inResponse);
			self.populatePicker(inResponse.membertype);
		}
		function onError(result){
			alert("Error in loading file...");
		}
	},
	populatePicker:function(membertype){
		// destroyClientControls will always reset and make sure there's no other child component
		// attached to memberTypePicker. It is a good practice to destroy before adding. 
		this.$.memberTypePicker.destroyClientControls();
 
		// inResponse returns 3 items in an array, so, we need to create 3 items in a loop.
		// See code below. 
 
		for(var i = 0;i < membertype.length;i++){
			this.$.memberTypePicker.createComponent(membertype[i]);	
		}
		this.$.memberTypePicker.render();
		// Done rendering of all membertype array into the component of picker.
 
	},
	getFormValues:function(){
		this.payLoad = {};
		this.payLoad.txtName = this.$.txtName.getValue();
		this.payLoad.txtPassword = this.$.txtPassword.getValue();
		this.payLoad.isMember = this.$.checkMember.getValue();
		if (this.$.pickerMemberType.selected != null){
			this.payLoad.memberType = this.$.pickerMemberType.selected.content;
		}
		this.payLoad.txtAddress = this.$.txtAddress.getValue();
		console.log(this.payLoad);
		return this.payLoad;
	}
});

Next, is to prepared the form so that, it will load external data dynamically assigning value to it. To do this exercise, I’ve prepare another local json file called “datafromserver.json”, also located at asset folder. Content of the json should look like this

{
	"data":{
		"name":"Mr. Robert Kawasaki",
		"password":"robert",
		"isMember":true,
		"membertype":"Gold",
		"address":"University of Southern California Los Angeles, CA 90033."
	}
}

For this tutorial, I’m going to use App.js to retrieve the content, then pass the values into SampleForm.js, using a method called setFormValues(). A typical enyo form should always have some form of set and get methods. Code below are my changes made in App.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
enyo.kind({
     name: "App",
     kind: "FittableRows", 
     classes: "enyo-fit enyo-unselectable",
     components: [
         { kind:"Header" },
         {   
             kind: "Scroller",
             name: "contentControl",
             fit:true,
             touch:true, 
             thumb:true,
             components:[
                { 
                  name:"registerFormControl",
                  kind:"SampleForm" 
                }
             ]
        },
        { 
           kind:"Footer",
           onSubmit:"handleFormSubmit" 
        }
    ],
    create: function(){
	this.inherited(arguments);
        this.loadStuffFromFile();
    },
    loadTextFile:function(url,onSuccess,onError){
        var ajaxGet =  new enyo.Ajax({
            url:url,
            method:'GET',
            handleAs:'json'
        }); 
        ajaxGet.go();
        ajaxGet.response(this, onSuccess);
        ajaxGet.error(this, onError);
  },
  loadStuffFromFile:function(){
      var self = this;
      this.loadTextFile('assets/datafromserver.json',onSuccess,onError);
      function onSuccess(inSender,inResponse){
          // Remember: always use a proxy variable in subfunctions.
          console.log(inResponse);
          self.pushToSampleForm(inResponse.data);
      }
      function onError(){
          alert("Error in loading file...");
      }
  },
 
  pushToSampleForm:function(param){
      // like how we getFormValues();, we use setFormValues() instead.
      this.$.registerFormControl.setFormValues(param);
  },
 
  handleFormSubmit:function(inSender,inEvent) {
      this.payLoad = this.$.registerFormControl.getFormValues();
      console.log(this.payLoad);
      var ajax = new enyo.Ajax({
          url: "http://www.yourgatewayurl.com",
          method:"POST",
          timeout:5000,
          contentType:"application/json"
      });
      ajax.go(this.payLoad);
      ajax.response(this, "processResponse");
      ajax.error(this, "processError");
  },
  processResponse:function(inSender,inResponse) {
      alert("All Done");
  },
  processError:function(inSender,inResponse) {
      alert("Failed");
  } 
});

Next, let’s move on to inserting a setFormValues method inside SampleForm.js.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
enyo.kind({
	name: "SampleForm",
	kind: "FittableRows", 
	classes: "enyo-fit enyo-unselectable padding15px formBg",
	components: [
		{ style:"height:20px" },
		{   
			kind: "onyx.InputDecorator",
			classes:"inputStyler", 
			components: [
				{
					name:"txtName", 
					kind: "onyx.Input", 
					placeholder: "Enter a Name",
					type:"text",
					attributes:{
						maxlength:80,
						required:"required"				
					}
				}
			] 	
		},
		{ style:"height:10px" },
		{   
			kind: "onyx.InputDecorator",
			classes:"inputStyler", 
			components: [
				{
					name:"txtPassword", 
					kind: "onyx.Input", 
					placeholder: "Enter Password",
					type:"password",
					attributes:{
						maxlength:10,
						required:"required"				
					}  
				}
			] 	
		},
		{ style:"height:10px" },
		{
			layoutKind: "FittableColumnsLayout",
			style:'height:32px',
			components:[
				{ 
					content:"Registered Member ? ",
					style:"width:200px;padding:8px;"
				},
				{
					name:"checkMember",
					kind:"onyx.Checkbox", 
					onchange:"checkboxChanged", 
					checked: true,
					style:"width:100px;"
				}
			]
		},
		{ style:"height:10px" },
		{
			name:"pickerMemberType",
			kind: "onyx.PickerDecorator", 
			components: [
				{
					kind: "onyx.PickerButton", 
					content: "Select Member Type...", 
					style: "width: 100%"
				},
				{
					// Notice, I deleted the components attributes with all it's child data.
					// Given the control a name to assign components into it.
					name:"memberTypePicker",
					kind: "onyx.Picker"
				}
			]
		},
		{ style:"height:10px" },
		{   
			kind: "onyx.InputDecorator",
			classes:"inputStyler", 
			components:[
				{
					kind:"onyx.TextArea",
					name:"txtAddress",
					style:'width:100%',
					placeholder:"Enter Address",
					attributes:{
						maxlength:300,
						required:"required"				
					} 
				}
			] 
		}  		
	],
	create: function(inSender,inEvent){
		this.inherited(arguments);
		this.loadDataForMemberType();
	},
	loadTextFile:function(url,onSuccess,onError){
		// A simple ajax called that have two callbacks as parameter.
		// returns itself back to the caller. 
		var ajaxGet =  new enyo.Ajax({
			url:url,
			method:'GET',
			handleAs:'json'
		});	
		ajaxGet.go();
		ajaxGet.response(this, onSuccess);
		ajaxGet.error(this, onError);
	},
 
	loadDataForMemberType:function(){
		var self = this;
		console.log("Loading data from membertype.json...");
		this.loadTextFile("assets/membertype.json",onSuccess,onError);
		function onSuccess(inSender,inResponse){
			// Take note whenever you are dealing with subfunction, "this" context may differ 
			// based on it's own closure. Best to assigned "this" to another variable. See line 112.
			// According to API documentation enyo.Ajax function always returns inSender, inResponse.
			// calling this.<functioname> here will result in error, so use self instead.
			console.log(inResponse);
			self.populatePicker(inResponse.membertype);
		}
		function onError(result){
			alert("Error in loading file...");
		}
	},
	populatePicker:function(membertype){
		// destroyClientControls will always reset and make sure there's no other child component
		// attached to memberTypePicker. It is a good practice to destroy before adding. 
		this.$.memberTypePicker.destroyClientControls();
 
		// inResponse returns 3 items in an array, so, we need to create 3 items in a loop.
		// See code below. 
 
		for(var i = 0;i < membertype.length;i++){
			this.$.memberTypePicker.createComponent(membertype[i]);	
		}
		this.$.memberTypePicker.render();
		// Done rendering of all membertype array into the component of picker.
	},
	getFormValues:function(){
		this.payLoad = {};
		this.payLoad.txtName = this.$.txtName.getValue();
		this.payLoad.txtPassword = this.$.txtPassword.getValue();
		this.payLoad.isMember = this.$.checkMember.getValue();
		if (this.$.pickerMemberType.selected != null){
			this.payLoad.memberType = this.$.pickerMemberType.selected.content;
		}
		this.payLoad.txtAddress = this.$.txtAddress.getValue();
		console.log(this.payLoad);
		return this.payLoad;
	},
	setFormValues:function(param){
		//Simply just set back the value to the form.
		this.$.txtName.setValue(param.name);
		this.$.txtPassword.setValue(param.password);
		this.$.checkMember.setValue(param.isMember);
		this.$.txtAddress.setValue(param.address);
		// To set the picker to "Gold", may required a special method that iterates through
		// the picker control's in key : value search. For that, we write some function like
		// findMatchingItem which matches the picker's content to param.membertype.
		this.matchingPickerControl = this.findMatchingItem(this.$.memberTypePicker,"content",param.membertype);
		this.$.memberTypePicker.setSelected(this.matchingPickerControl);
	},	
 
	findMatchingItem : function( controlName, key, stringResults ){
   		var resultKey;
   		var len = controlName.controls.length;
   		var i;
   		for(i = 0; i < len; i++){
   			if (controlName.controls[i][key] == stringResults){
   				resultKey = controlName.controls[i];
   				break;
   			}
   		}
   		return resultKey;
   	},
});

Well, there you have it, a complete cycle of get form data and set form data. Like always, today’s tutorial files

Enyo Tutorial #6 (1362 downloads)

 

Comments

comments

Leave a Reply

Your email address will not be published. Required fields are marked *