<!-- 
/*
Copyright 2017 apHarmony

This file is part of jsHarmony.

jsHarmony is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

jsHarmony is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public License
along with this package.  If not, see <http://www.gnu.org/licenses/>.
*/
-->
<script type="text/x-tutorial-info">
{
  "Title": "Layout: Form",
  "Menu": ["Models","Forms"],
  "Code": [
    "/models/FormBasic_Standard.json",
    "/models/FormBasic_Subform.json",
    "/models/FormBasic_Tabbed.json",
    "/models/FormBasic_Unbound.json",
    "/models/FormBasic_CustomSQL.json",
    "/models/FormBasic_Controls.json",
    "/models/FormBasic_HTMLContent.json",
    "/models/FormBasic_HTMLContent.ejs",
    "/models/FormBasic_EditableDefault.json"
  ],
  "Demo": [
    { "url": "jsHarmonyTutorials/FormBasic_Standard?action=update&cust_id=1", "title": "Standard Form" },
    { "url": "jsHarmonyTutorials/FormBasic_Subform_Cust?action=update&cust_id=1", "title": "Parent / Subform" },
    { "url": "jsHarmonyTutorials/FormBasic_Tabbed_Cust_Container?action=update&cust_id=1", "title": "Tabbed Form", "windowparams": "width=1200,height=700" },
    { "url": "jsHarmonyTutorials/FormBasic_Unbound", "title": "Unbound Form" },
    { "url": "jsHarmonyTutorials/FormBasic_CustomSQL?action=insert", "title": "Custom SQL" },
    { "url": "jsHarmonyTutorials/FormBasic_Controls?action=update&cust_id=1", "title": "Form Controls" },
    { "url": "jsHarmonyTutorials/FormBasic_HTMLContent", "title": "HTML Content" },
    { "url": "jsHarmonyTutorials/FormBasic_EditableDefault?action=insert&cust_sts=ACTIVE", "title": "Editable Default Querystring Value" }
  ]
}
</script>

<h3>Introduction</h3>
Forms enable editing data, one record at a time.  Grids usually list rows, and then link to forms for further editing.<br/>
<br/>
Forms are defined by setting the "layout" to "form".

<h4>Standard Form</h4>
<%-getScreenshot('jsHarmonyTutorials/FormBasic_Standard?action=update&cust_id=2&popup=1','Basic Form')%>
<pre>
{
  "table":"cust",
  "layout":"form",
  "onecolumn":true,
  "caption":["Customer","Customers"],
  "fields":[
    {"name":"cust_id","caption": "ID"},
    {"name":"cust_name","caption":"Name"},
    {"name":"cust_sts","caption":"Status"}
  ]
}
</pre>

<h4>Form with Subforms</h4>
Forms can contain subforms:
<%-getScreenshot('jsHarmonyTutorials/FormBasic_Subform_Cust?action=update&cust_id=1&popup=1','Form w/Subform')%>
<pre>
//Parent Form
"Cust": {
  "table":"cust",
  "layout":"form",
  "onecolumn":true,
  "caption":["Customer","Customers"],
  "fields":[
    {"name":"cust_name","caption":"Name"},
    {"name":"cust_sts","caption":"Status"},
    {"control": "subform","target": "CustAddr"}
  ]
}

//Subform
"CustAddr": {
  "table":"cust_addr",
  "layout":"form-m",
  "onecolumn":true,
  "caption":["Address","Addresses"],
  "fields":[
    {"name":"cust_addr_country","caption":"Country"},
    {"name":"cust_addr_line1","caption":"Address"},
    {"name":"cust_addr_line2","caption":""},
    {"name":"cust_addr_city","caption":"City"},
    {"name":"cust_addr_state","caption":"State"},
    {"name":"cust_addr_zip","caption":"Zip"}
  ]
}
</pre>

<h4>Tabbed Forms</h4>
Forms can be tabbed:
<%-getScreenshot('jsHarmonyTutorials/FormBasic_Tabbed_Cust_Container?action=update&cust_id=1&popup=1','Tabbed Form')%>
<pre>
//Tabbed Parent Form
"FormBasic_Tabbed_Cust_Container": {
  "table":"cust",
  "layout":"form",
  "caption":["Customer","Customers"],
  "tabpanelstyle":"min-width:500px;",
  "tabs":[
    {"name":"Overview","target":"FormBasic_Tabbed_Cust"},
    {"name":"Contacts","caption": "Contacts","target":"FormBasic_Tabbed_CustContact_Listing"}
  ]
}

//Overview Tab
"FormBasic_Tabbed_Cust": {
  "table":"cust",
  "layout":"form",
  "onecolumn":true,
  "caption":["Customer","Customers"],
  "fields":[
    {"name":"cust_name","caption":"Name"},
    {"name":"cust_sts","caption":"Status"}
  ]
}

//Contacts Tab
"FormBasic_Tabbed_CustContact_Listing": {
  "table":"cust_contact",
  "layout":"grid",
  "caption":["Contact","Contacts"],
  "fields":[
    {"name":"cust_contact_name","caption":"Name"},
    {"name":"cust_contact_title","caption":"Title"},
    {"name":"cust_contact_email","caption":"Email"}
  ]
}
</pre>

<h4>Unbound Forms</h4>
Unbound forms are fully disconnected from any database access, except via JavaScript API calls.
<%-getScreenshot('jsHarmonyTutorials/FormBasic_Unbound?popup=1','Unbound Form')%>
<pre>
{
  "layout":"form",
  "unbound":1,
  "title":"Message",
  "fields":[
    {"control":"html","value":"Lorem ipsum dolor sit amet, consectetur adipiscing elit."}
  ]
}
</pre>

<h4>Fully Custom Forms</h4>
Forms can also use fully custom JS / HTML.  More information is available in the <a href="/tutorials/form_custom">Custom Form</a> tutorial.

<h3>Form SQL / Datasource</h3>
A form's datasource is a table or view.  The database table or view is defined by the "table" property.  The database statements (Browse / Insert / Update / Delete) are automatically generated based on the table and fields.<br/>
<br/>
It is best practice to use a table, since primary keys and foreign keys can be automatically read from the database.  However, editable views can also be used if the primary / foreign keys are defined in the models using the "key" and "foreignkey" properties.

<h4>Custom SQL</h4>
Custom SQL can be used to override any of the SQL statements.  For example:
<pre>
{
  "table":"cust",
  "layout":"form",
  "onecolumn":true,
  "caption":["Customer","Customers"],
  "sqlinsert":"%%%SQL%%%; update cust set cust_start_dt = date('now', 'localtime');",
  "fields":[
    {"name":"cust_id","caption": "ID"},
    {"name":"cust_name","caption":"Name"},
    {"name":"cust_sts","caption":"Status"},
    {"name":"cust_start_dt","caption":"Start Date","control":"label"}
  ]
}
</pre>
Please note, custom SQL should generally not be used.  Database-level business logic should be implemented using database triggers.<br/>
<br/>
More information on custom SQL is available in the <a href="/tutorials/model_database_sql">Database / SQL</a> tutorial.

<h3>Form Fields / Controls</h3>
The "fields" property defines the fields that are selected from the database.<br/>
<br/>
Primary keys are automatically added to the table, if they are defined as primary keys in the database.  Foreign keys for tables are automatically added when required by bindings.<br/>
<br/>
A variety of controls are available.  The control can be set using the "control" property:
<%-getScreenshot('jsHarmonyTutorials/FormBasic_Controls?action=update&cust_id=1&popup=1','Form Controls')%>
<pre>
{
  "table":"cust",
  "layout":"form",
  "onecolumn":true,
  "caption":["Customer","Customers"],
  "fields":[
    {"name":"cust_id","caption": "ID"},
    {"name":"cust_name","caption":"Name","control":"textzoom"},
    {"name":"cust_sts","caption":"Status","control":"dropdown_L"},
    {"name":"cust_start_dt","caption":"Start Date","control":"date_mmddyy"},
    {"name":"cust_desc","caption":"Notes","control":"textarea"}
  ]
}
</pre>
More information about form fields and controls is available in the <a href="/tutorials/fields_overview">Fields</a> tutorials.

<h3>HTML Content</h3>
Additional HTML can be added to a form by creating a MODEL.ejs file.
<%-getScreenshot('jsHarmonyTutorials/FormBasic_HTMLContent?popup=1','Form HTML Content')%>
<pre>
//FORM.json
{
  "layout":"form",
  "unbound":1,
  "title":"HTML Content"
}

//FORM.ejs
<h2>Sample Content</h2>
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
</pre>

<h3>Querystring</h3>

<h3 data-level="2">Insert vs Browse vs Update Mode</h3>
Forms can be acccessed in either "insert", "browse", or "update" mode.

<h4>Insert Mode</h4>
Insert mode is accessed by adding "?action=insert" to the querystring:<br/>
<br/>
<a href="/jsHarmonyTutorials/FormBasic_Standard?action=insert" target="_blank">/jsHarmonyTutorials/FormBasic_Standard?action=insert</a>
<%-getScreenshot('jsHarmonyTutorials/FormBasic_Standard?action=insert&popup=1','Form Insert Mode')%>

<h4>Browse Mode</h4>
Browse mode is accessed by adding "?action=browse&PRIMARYKEY=VALUE" to the querystring:<br/>
<br/>
<a href="/jsHarmonyTutorials/FormBasic_Standard?action=browse&cust_id=1" target="_blank">/jsHarmonyTutorials/FormBasic_Standard?action=browse&amp;cust_id=1</a>
<%-getScreenshot('jsHarmonyTutorials/FormBasic_Standard?action=browse&cust_id=1&popup=1','Form Browse Mode')%>

<h4>Update Mode</h4>
Update mode is accessed by adding "?action=update&PRIMARYKEY=VALUE" to the querystring:<br/>
<br/>
<a href="/jsHarmonyTutorials/FormBasic_Standard?action=update&cust_id=1" target="_blank">/jsHarmonyTutorials/FormBasic_Standard?action=update&amp;cust_id=1</a>
<%-getScreenshot('jsHarmonyTutorials/FormBasic_Standard?action=update&cust_id=1&popup=1','Form Update Mode')%>

<h3 data-level="2">Default Values</h3>
Default values can be set on insert by adding the field value to the querystring:<br/>
<br/>
<a href="/jsHarmonyTutorials/FormBasic_Standard?action=insert&cust_sts=ACTIVE" target="_blank">/jsHarmonyTutorials/FormBasic_Standard?action=insert&amp;cust_sts=ACTIVE</a>
<%-getScreenshot('jsHarmonyTutorials/FormBasic_Standard?action=insert&cust_sts=ACTIVE&popup=1','Form Insert Mode Default Value')%>

<h4>Always Editable on Insert</h4>
Passing a default value will make the field read-only.  In order to keep the field editable, set the "locked_by_querystring" property to false:

<pre>
{
  "fields":[
    { "name":"cust_sts", "caption":"Status", "locked_by_querystring":false }
  ]
}
</pre>
<%-getScreenshot('jsHarmonyTutorials/FormBasic_EditableDefault?action=insert&cust_sts=ACTIVE&popup=1','Form Insert Mode Default Value Editable')%>