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 (1371 downloads)