Making a Form on the Canvas
Tags: canvas, form, zim, zimjs
Published: 2021-01-06 03:06:52

Here is a survey form on the HTML Canvas https://zimjs.com/survey/index.html?id=dev

![Survey on Canvas](https://dev-to-uploads.s3.amazonaws.com/i/8rdt73jfgrs1kdtn0v7c.jpg)

In this example we put a question on a page and use the arrows or swipe to go to the next question - but we could put as many questions on a page we want.  We use a ZIM Indicator() at the bottom to show which page we are on and how many there are.

--- 

####COMPONENTS
There are many components in ZIM that help with questions.  There are traditional ZIM RadioButtons, CheckBox, TextArea, Button, etc.  In this survey we feature a Stepper() - seen above - which steps through numbers or strings and a Selector() which can work in a grid or row or column - seen below.

![ZIM Selector Component](https://dev-to-uploads.s3.amazonaws.com/i/xo108v1xggyp19ff9c9w.jpg)

--- 

####BIND
We set up ZIM Bind() to handle the data we want to send to the database:

```JavaScript
const bind = new Bind({
    connection:"https://zimjs.com/survey/data.php", 
    bindType:POST, // set to GET to test from local file
    master:id, // this comes from the query string
    report:true // see data reports in the console
}); 
```

--- 

####STEPPER
Here is the code for a page with a Stepper and we bind the stepper currentValue to a bindID that is received on the server side:

```JavaScript
const page4 = new Page(backing.width, backing.height, orange, green);
new Label({text:"How many YEARS have you used ZIM?", group:"question"})
    .pos(0,padding,CENTER,TOP,page4);
new Stepper({
    list:[0,.5,1,1.5,2,3,4,5,6],
    width:250
}).center(page4).mov(0,20).bind("years", "currentValue");
```

--- 

####STYLE
The components are styled with ZIM STYLE.  Note that all labels will be Reuben but labels grouped with "question" will be arial.  So group styles are similar to classes in CSS.

```JavaScript
STYLE = {
    type:{
        Label:{
            color:dark,
            font:"Reuben",
            size:30
        },        
        Stepper:{
            backgroundColor:yellow.lighten(.1),
            color:dark
        }
    },
    group:{
        question:{
            font:"arial",
            size:35
        }
    }    
}
```

--- 

####SUBMIT
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/mx9hcuffvqa1oxc5k42h.jpg)

Here is the code for the page with the Submit button and where we send the data in Bind to the server.  We receive a callback function and go to the final page or pop up an error message:

```JavaScript
const page10 = new Page(stageW, backing.height, yellow, orange);
new Label({text:"Please submit the survey...", group:"question"})
    .pos(0,padding,CENTER,TOP,page10);
new Button({label:"SUBMIT"})
    .center(page10).mov(0,padding/2).tap(()=>{                
        bind.to({
            call:result=>{
                if (result.success) pages.go(page11, null, "fan");
                else error.show();
            }
        });        
    });    
const error = new Pane(300, 220, "ERROR", red);
```

--- 

####PAGES
The pages are all added to ZIM Pages() which handles swiping including traditional transitions or cool ZIM Emitter() transitions.  ZIM Arrow() objects work with pages to travel through the pages.

```JavaScript
const pages = new Pages([
    page1, page2, page3, page4, page5, 
    page6, page7, page8, page9, page10, 
    page11
], "lineZIM", .4, null, backing)
    .center(backing);

const next = new Arrow(blue, blue.lighten(.2), pages, RIGHT, "thick")
    .sca(1.5).pos(40,30,RIGHT,BOTTOM);
const prev = new Arrow(blue, blue.lighten(.2), pages, LEFT, "thick")
    .sca(1.5).rot(180).pos(40,30,LEFT,BOTTOM);
```

--- 

####INDICATOR AND WIRED
The ZIM Indicator is wired to the Pages index to automatically change as the pages change.  ZIM wire() and wired() are an alternative to traditional on() methods in ZIM - we could have just used a change method. The Pages have one extra results page so we use a filter on wired() to turn off the indicator when on the last page.  Bind also has filters. 

```JavaScript
new Indicator(400,35,10,green)
    .pos(0,49,CENTER,BOTTOM)
    .wired({
        source:pages, 
        input:"index",
        prop:"selectedIndex", 
        // turn indicator off for last page
        filter:function(v) {return v>=10?-1:v;} 
    });
```

--- 

####BASE 
On the server side we use ZIM Base to wrap MySQLi at 1/3 the size.  Here is the PHP:

```PHP
<?php
require_once('../zim_base.php'); // see https://zimjs.com/base

// ZIM Bind() is sending a master id for each person we contact 
$data = [uid=>$master, date=>"NOW()"];

// often the data is just added to the database as JSON 
// but here we want to make individual fields for reporting 
// so use simplify() which flattens the data as a key value array
// add this to the custom data above
$data = array_merge($data, $base->simplify());

$result = $base->insert("zim_survey", $data);

if ($result->affected_rows > 0) $base->reply("success", "data added"); 
else $base->reply("error", "cannot store data"); 
?>
```

---

Here is a ZIM Explore video that takes you through all this and more in one amazing hour!  Really... considering ZIM is a front-end Canvas Framework for visual apps - can the data handling get much better? https://www.youtube.com/watch?v=Bt6mMKTrzlk

---

If you have not checked out the Canvas recently - you simply must!  Here is the [ZIM&nbsp;Dev&nbsp;Site](https://dev.zimjs.com) and some [In-depth&nbsp;Guides](https://drabstract.medium.com/) by Dr&nbsp;Abstract including [Your Guide to Coding Creativity on the Canvas](https://drabstract.medium.com/your-guide-to-coding-creativity-on-the-canvas-ada0996298f6).