Here contain 2 modules:
1. Form Builder: To create any of of form to display in frontend
2. Form Submission: This is a admin panel to see all form submissions
| File | Folder Link |
|---|---|
| M - 3 files | \\SYNAS\Allan\DOCUMENTATION\Module\Form Builder & Form Submission\rckuc\wolf\app\models |
| V - 3 folders | \\SYNAS\Allan\DOCUMENTATION\Module\Form Builder & Form Submission\rckuc\wolf\app\views |
| C - 2 files | \\SYNAS\Allan\DOCUMENTATION\Module\Form Builder & Form Submission\rckuc\wolf\app\controllers |
| backend.php | \\SYNAS\Allan\DOCUMENTATION\Module\Form Builder & Form Submission\rckuc\wolf\app\layouts |
| Backend - style.css | \\SYNAS\Allan\DOCUMENTATION\Module\Form Builder & Form Submission\rckuc\wolf\admin\themes\black_and_white |
| Backend - Javascript files | \\SYNAS\Allan\DOCUMENTATION\Module\Form Builder & Form Submission\rckuc\wolf\admin\javascript |
| mailer.php | \\SYNAS\Allan\DOCUMENTATION\Module\Form Builder & Form Submission\rckuc\wolf\frontend |
| Frontend - default.css | \\SYNAS\Allan\DOCUMENTATION\Module\Form Builder & Form Submission\rckuc\public\themes\rckuc\css |
| Frontend - Javascript | \\SYNAS\Allan\DOCUMENTATION\Module\Form Builder & Form Submission\rckuc\public\themes\rckuc\js |
| .user.ini | \\SYNAS\Allan\DOCUMENTATION\Module\Form Builder & Form Submission\rckuc |
| wolf_business_profile.sql & wolf_business_branch.sql | \\SYNAS\Allan\DOCUMENTATION\Module\Form Builder & Form Submission |
Update: backend.php
<head>
<script type="text/javascript" src="<?php echo URI_PUBLIC; ?>wolf/admin/javascripts/form_builder.js"></script>
<script type="text/javascript" src="<?php echo URI_PUBLIC; ?>wolf/admin/javascripts/form_submission.js"></script>
<!-- Include FORMEO JS -->
<link rel="stylesheet" href="<?php echo URI_PUBLIC; ?>wolf/admin/javascripts/formeo.min.css">
<script type="text/javascript" charset="utf-8" src="<?php echo URI_PUBLIC; ?>wolf/admin/javascripts/formeo.min.js"></script>
</head>
<!-- Add 2 Tabs -->
<body id="body_<?php echo $ctrl.'_'.Dispatcher::getAction(); ?>">
<ul>
<li id="page-plugin" class="plugin"><a href="<?php echo get_url('form_builder'); ?>"<?php if ($ctrl=='form_builder') echo ' class="current"'; ?>><?php echo __('Form Builder'); ?></a></li>
<li id="page-plugin" class="plugin"><a href="<?php echo get_url('form_submission'); ?>"<?php if ($ctrl=='form_submission') echo ' class="current"'; ?>><?php echo __('Form Submission'); ?></a></li>
</ul>
</body>
<head>
<script type="text/javascript" src="<?php echo URI_PUBLIC; ?>wolf/admin/javascripts/form_builder.js"></script>
<script type="text/javascript" src="<?php echo URI_PUBLIC; ?>wolf/admin/javascripts/form_submission.js"></script>
<!-- Include FORMEO JS -->
<link rel="stylesheet" href="<?php echo URI_PUBLIC; ?>wolf/admin/javascripts/formeo.min.css">
<script type="text/javascript" charset="utf-8" src="<?php echo URI_PUBLIC; ?>wolf/admin/javascripts/formeo.min.js"></script>
</head>
<!-- Add 2 Tabs -->
<body id="body_<?php echo $ctrl.'_'.Dispatcher::getAction(); ?>">
<ul>
<li id="page-plugin" class="plugin"><a href="<?php echo get_url('form_builder'); ?>"<?php if ($ctrl=='form_builder') echo ' class="current"'; ?>><?php echo __('Form Builder'); ?></a></li>
<li id="page-plugin" class="plugin"><a href="<?php echo get_url('form_submission'); ?>"<?php if ($ctrl=='form_submission') echo ' class="current"'; ?>><?php echo __('Form Submission'); ?></a></li>
</ul>
</body>
Update: model Page.php
Update function for includeSnippet()
To key in form name in $vars so that we can display any form
public function includeSnippet($name, $vars = []) {
$snippet = Snippet::findByName($name);
if (false !== $snippet) {
// Extract variables into scope for the snippet
extract($vars);
eval('?>'.$snippet->content_html);
return true;
}
return false;
}
public function includeSnippet($name, $vars = []) {
$snippet = Snippet::findByName($name);
if (false !== $snippet) {
// Extract variables into scope for the snippet
extract($vars);
eval('?>'.$snippet->content_html);
return true;
}
return false;
}
Insert SQL Record into wolf_module_setting:
Add 2 settings:
INSERT INTO `wolf_module_setting`
(`id`, `module`, `name`, `value_type`, `value`, `created_on`, `updated_on`, `created_by_id`, `updated_by_id`)
VALUES
(NULL, 'form_builder', 'Data Sitekey', 'textarea', '***Replace Your Data Sitekey***', NOW(), NULL, NULL, NULL),
(NULL, 'form_builder', 'Secret', 'textarea', '***Replace Your Secret***', NOW(), NULL, NULL, NULL);
INSERT INTO `wolf_module_setting`
(`id`, `module`, `name`, `value_type`, `value`, `created_on`, `updated_on`, `created_by_id`, `updated_by_id`)
VALUES
(NULL, 'form_builder', 'Data Sitekey', 'textarea', '***Replace Your Data Sitekey***', NOW(), NULL, NULL, NULL),
(NULL, 'form_builder', 'Secret', 'textarea', '***Replace Your Secret***', NOW(), NULL, NULL, NULL);
Update: style.css
/* FORM BUILDER */
.save-form {
display: none !important;
}
#email_template {
display: none;
}
#email_list {
display: flex;
flex-direction: column;
}
#email_list input {
width: 20rem;
}
.email_container {
display: flex;
align-items: center;
justify-content: flex-start;
gap: 0.5rem;
margin-bottom: 0.5rem;
}
.delete_email {
cursor: pointer;
height: 20px;
width: 20px;
}
.email_container:first-child > img {
display: none;
}
#preview_form_container {
background-color: lightgray;
padding: 1rem;
margin-bottom: 1rem;
}
#formeo-editor h1,
#preview_form_container h1 {
color: unset;
background-color: unset;
text-shadow: unset;
margin: unset;
}
#formeo-editor .field-attrs-name,
#formeo-editor input[value="select_first_option"],
#formeo-editor .options-panel input.name,
#formeo-editor .options-panel input.value {
display: none;
}
/* FORM SUBMISSSION */
#body_form_submission_index #content-wrapper {
width: 95%;
float: unset;
margin: 1rem auto;
}
.email_data_table {
margin: auto;
}
.email_data_table th,
.email_data_table td {
border-bottom: 1px solid #ddd !important;
padding: 0.5rem !important;
text-align: left;
}
.email_data_table td {
border-color: #eee !important;
}
.email_data_table th:nth-child(2),
.email_data_table td:nth-child(2) {
padding-left: 1rem !important;
}
/* FORM BUILDER */
.save-form {
display: none !important;
}
#email_template {
display: none;
}
#email_list {
display: flex;
flex-direction: column;
}
#email_list input {
width: 20rem;
}
.email_container {
display: flex;
align-items: center;
justify-content: flex-start;
gap: 0.5rem;
margin-bottom: 0.5rem;
}
.delete_email {
cursor: pointer;
height: 20px;
width: 20px;
}
.email_container:first-child > img {
display: none;
}
#preview_form_container {
background-color: lightgray;
padding: 1rem;
margin-bottom: 1rem;
}
#formeo-editor h1,
#preview_form_container h1 {
color: unset;
background-color: unset;
text-shadow: unset;
margin: unset;
}
#formeo-editor .field-attrs-name,
#formeo-editor input[value="select_first_option"],
#formeo-editor .options-panel input.name,
#formeo-editor .options-panel input.value {
display: none;
}
/* FORM SUBMISSSION */
#body_form_submission_index #content-wrapper {
width: 95%;
float: unset;
margin: 1rem auto;
}
.email_data_table {
margin: auto;
}
.email_data_table th,
.email_data_table td {
border-bottom: 1px solid #ddd !important;
padding: 0.5rem !important;
text-align: left;
}
.email_data_table td {
border-color: #eee !important;
}
.email_data_table th:nth-child(2),
.email_data_table td:nth-child(2) {
padding-left: 1rem !important;
}
Create New Layout: mailer-php under 'Layouts' Tab
Then insert this code:
<?php include('wolf/frontend/mailer.php'); ?>
<?php include('wolf/frontend/mailer.php'); ?>
Introduction : mailer.php
This is a php script to:
Create New Page: mailer-php under 'Pages' Tab
Create New Snippet: js-formeo
Introduction render-form:
<link rel="stylesheet" href="<?php echo THEME_PATH ?>js/formeo.min.css">
<script src="<?php echo THEME_PATH ?>js/formeo.min.js"></script>
<script src="<?php echo THEME_PATH ?>js/render_form.js"></script>
<link rel="stylesheet" href="<?php echo THEME_PATH ?>js/formeo.min.css">
<script src="<?php echo THEME_PATH ?>js/formeo.min.js"></script>
<script src="<?php echo THEME_PATH ?>js/render_form.js"></script>
Create New Snippet: render-form
<?php
$form_name = $vars['form_name'] ?? '';
$form = FormBuilder::findByFormName($form_name);
if ($form->status == 1) {
$hiddenFields = [
'ajax_url_mailer' => URL_PUBLIC . 'mailer-php',
'email_subject' => $form->name ?? '',
'email_to' => $form->email_to ?? '',
'show_label' => $form->show_label ?? '',
'show_placeholder' => $form->show_placeholder ?? '',
'auto_reply' => $form->auto_reply ?? '',
'auto_subject' => $form->auto_subject ?? '',
'auto_header' => $form->auto_header ?? '',
'auto_body' => $form->auto_body ?? '',
'auto_footer' => $form->auto_footer ?? '',
'success_msg' => $form->success_msg ?? 'Email Submitted Successfully',
'error_msg' => $form->error_msg ?? 'Email Submit Failed',
];
foreach ($hiddenFields as $id => $value) {
// Escape value except for success_msg/error_msg if you trust them
$escapedValue = htmlspecialchars($value, ENT_QUOTES);
echo "<input id=\"$id\" type=\"hidden\" value=\"$escapedValue\">";
}
$countries = Country::findAll();
echo '<div class="country_code_list">';
foreach ($countries as $country) {
if (!empty($country->country_phone_code)) {
echo '<div data-code="'.$country->country_phone_code.'">'.$country->country_name.' ('.$country->country_phone_code.')</div>';
}
}
echo '</div>';
echo '<form action="" enctype="multipart/form-data" data-form="'.htmlspecialchars($form->form_json, ENT_QUOTES).'"></form>';
?>
<?php } ?>
<?php
$form_name = $vars['form_name'] ?? '';
$form = FormBuilder::findByFormName($form_name);
if ($form->status == 1) {
$hiddenFields = [
'ajax_url_mailer' => URL_PUBLIC . 'mailer-php',
'email_subject' => $form->name ?? '',
'email_to' => $form->email_to ?? '',
'show_label' => $form->show_label ?? '',
'show_placeholder' => $form->show_placeholder ?? '',
'auto_reply' => $form->auto_reply ?? '',
'auto_subject' => $form->auto_subject ?? '',
'auto_header' => $form->auto_header ?? '',
'auto_body' => $form->auto_body ?? '',
'auto_footer' => $form->auto_footer ?? '',
'success_msg' => $form->success_msg ?? 'Email Submitted Successfully',
'error_msg' => $form->error_msg ?? 'Email Submit Failed',
];
foreach ($hiddenFields as $id => $value) {
// Escape value except for success_msg/error_msg if you trust them
$escapedValue = htmlspecialchars($value, ENT_QUOTES);
echo "<input id=\"$id\" type=\"hidden\" value=\"$escapedValue\">";
}
$countries = Country::findAll();
echo '<div class="country_code_list">';
foreach ($countries as $country) {
if (!empty($country->country_phone_code)) {
echo '<div data-code="'.$country->country_phone_code.'">'.$country->country_name.' ('.$country->country_phone_code.')</div>';
}
}
echo '</div>';
echo '<form action="" enctype="multipart/form-data" data-form="'.htmlspecialchars($form->form_json, ENT_QUOTES).'"></form>';
?>
<?php } ?>
Update: default.css
/* Formeo Form */
#formeo-form { background-color: #f3f3f3; border-bottom: solid 8px #f7a81b; }
div.g-recaptcha {
margin: 0;
}
.form-message {
text-align: center;
/* padding-bottom: 1rem; */
}
.form-message.info {
color: #0050a2;
}
.form-message.success {
color: green;
}
.form-message.error {
color: red;
}
.dots::after {
content: '';
display: inline-block;
width: 1em;
text-align: left;
animation: dots 1s steps(3,end) infinite;
}
@keyframes dots {
0% { content: ''; }
33% { content: '.'; }
66% { content: '..'; }
100% { content: '...'; }
}
/* Move the form under menu header */
#formeo-form {
scroll-margin-top: 100px;
font-family: 'Work Sans', Arial, Helvetica, sans-serif;
}
/* Text <select> in will overflow, so change font-family */
#formeo-form form * {
font-family: 'Work Sans', Arial, Helvetica, sans-serif !important;
}
.formeo.formeo-render .formeo-column {
padding: 0 8px;
}
#formeo-form input.text,
#formeo-form textarea.text,
#formeo-form select.text {
/* width: 88.8%; */
background-color: #fff;
padding: 14px 20px;
/* margin: 0 1rem; */
font-size: 15px;
position: relative;
z-index: 1;
font-family: 'Open Sans', Arial, Helvetica, sans-serif;
line-height: 1;
border: solid 1px #cecece;
height: unset;
border-radius: unset;
}
#formeo-form select.text {
color: #999;
appearance: none;
-webkit-appearance: none;
-moz-appearance: none;
background-image: url(images/dropdown-icon.png);
background-repeat: no-repeat;
background-position: right 1rem center;
background-size: 1rem;
}
#formeo-form select.text option:not([disabled]) {
color: black;
}
#formeo-form select.text.has-value {
color: unset;
}
#formeo-form input[type="submit"].btn-blue {
border: none;
cursor: pointer;
outline: none;
background-color: #0050a2;
padding: 18px 35px;
color: #f7a81b;
font-weight: bold;
font-size: 14px;
border-radius: 30px;
min-width: 100px;
text-align: center;
text-transform: uppercase;
width: unset;
height: unset;
line-height: unset;
float: right;
}
#formeo-form input[type='file'] {
opacity: 0;
padding: 23px 20px;
}
#formeo-form .holder {
flex: 1;
border: solid 1px #cecece;
background-color: white;
position: relative;
}
#formeo-form .custom-file-label {
color: black;
cursor: pointer;
position: absolute;
top: 0;
left: 0;
height: 100%;
width: 30%;
display: flex;
align-items: center;
justify-content: center;
background-color: #F3F3F3;
border-right: 1px solid #cecece;
}
#formeo-form .custom-file-name {
position: absolute;
top: 0;
left: 30%;
height: 100%;
width: 70%;
padding: 0 1.5rem;
display: flex;
align-items: center;
}
#formeo-form .custom-file-name.placeholder {
color: #999;
}
#formeo-form .file-input:valid + .custom-file-label::after {
content: ' - ' attr(data-file-name);
}
@media only screen and (max-width: 768px) {
#formeo-form .formeo-row {
flex-direction: column;
padding: 0;
gap: 1em;
}
#formeo-form input[type="submit"].btn-blue {
display: block;
margin: 0 auto;
float: unset !important;
}
#formeo-form .formeo-column {
width: 100% !important;
padding: 0;
}
}
#formeo-form .error {
border-color: red !important;
}
#formeo-form select.error {
color: red;
}
#formeo-form .holder.error {
border-color: red;
}
/* To style radio & checkbox red if error */
#formeo-form input[type='radio'].error,
#formeo-form input[type='checkbox'].error {
visibility: hidden;
}
#formeo-form input[type='radio'].error:after,
#formeo-form input[type='checkbox'].error:after {
width: 0.5rem;
height: 0.5rem;
content: '';
display: inline-block;
visibility: visible;
border: 0.1rem solid red;
}
#formeo-form input[type='radio'].error:after {
border-radius: 0.5rem;
}
.contact_number_container {
position: relative;
}
.country_code_button {
position: absolute;
z-index: 10;
height: 100%;
display: flex;
align-items: center;
justify-content: flex-start;
width: 50px;
padding: 0 15px;
cursor: pointer;
background-image: url(images/dropdown-icon.png);
background-repeat: no-repeat;
background-position: right center;
background-size: 1rem;
}
.contact_number_container > input[type='tel'] {
padding-left: 100px !important;
}
.country_code_list {
display: none;
position: absolute;
top: 47px;
left: 0;
border: solid 1px #cecece;
max-height: 20rem;
overflow-x: auto;
cursor: pointer;
background-color: white;
z-index: 10;
}
.country_code_list > div {
display: flex;
align-items: center;
justify-content: flex-start;
padding: 0.5rem;
}
.country_code_list > div:hover {
background-color: lightgray;
}
#formeo-form .btn-wrapper {
position: relative;
display: inline-block;
float: right;
}
/* Loading state: hide text */
#formeo-form .btn-wrapper.loading input {
color: transparent; /* hide the button text */
pointer-events: none;
}
/* The spinner overlay */
#formeo-form .btn-wrapper.loading::after {
content: "";
position: absolute;
top: 50%;
left: 50%;
width: 20px;
height: 20px;
transform: translate(-50%, -50%);
border: 3px solid #f7a81b;
border-top-color: transparent;
border-radius: 50%;
animation: spin 0.8s linear infinite;
z-index: 2;
}
@keyframes spin {
to {
transform: translate(-50%, -50%) rotate(360deg);
}
}
/* Formeo Form */
#formeo-form { background-color: #f3f3f3; border-bottom: solid 8px #f7a81b; }
div.g-recaptcha {
margin: 0;
}
.form-message {
text-align: center;
/* padding-bottom: 1rem; */
}
.form-message.info {
color: #0050a2;
}
.form-message.success {
color: green;
}
.form-message.error {
color: red;
}
.dots::after {
content: '';
display: inline-block;
width: 1em;
text-align: left;
animation: dots 1s steps(3,end) infinite;
}
@keyframes dots {
0% { content: ''; }
33% { content: '.'; }
66% { content: '..'; }
100% { content: '...'; }
}
/* Move the form under menu header */
#formeo-form {
scroll-margin-top: 100px;
font-family: 'Work Sans', Arial, Helvetica, sans-serif;
}
/* Text <select> in will overflow, so change font-family */
#formeo-form form * {
font-family: 'Work Sans', Arial, Helvetica, sans-serif !important;
}
.formeo.formeo-render .formeo-column {
padding: 0 8px;
}
#formeo-form input.text,
#formeo-form textarea.text,
#formeo-form select.text {
/* width: 88.8%; */
background-color: #fff;
padding: 14px 20px;
/* margin: 0 1rem; */
font-size: 15px;
position: relative;
z-index: 1;
font-family: 'Open Sans', Arial, Helvetica, sans-serif;
line-height: 1;
border: solid 1px #cecece;
height: unset;
border-radius: unset;
}
#formeo-form select.text {
color: #999;
appearance: none;
-webkit-appearance: none;
-moz-appearance: none;
background-image: url(images/dropdown-icon.png);
background-repeat: no-repeat;
background-position: right 1rem center;
background-size: 1rem;
}
#formeo-form select.text option:not([disabled]) {
color: black;
}
#formeo-form select.text.has-value {
color: unset;
}
#formeo-form input[type="submit"].btn-blue {
border: none;
cursor: pointer;
outline: none;
background-color: #0050a2;
padding: 18px 35px;
color: #f7a81b;
font-weight: bold;
font-size: 14px;
border-radius: 30px;
min-width: 100px;
text-align: center;
text-transform: uppercase;
width: unset;
height: unset;
line-height: unset;
float: right;
}
#formeo-form input[type='file'] {
opacity: 0;
padding: 23px 20px;
}
#formeo-form .holder {
flex: 1;
border: solid 1px #cecece;
background-color: white;
position: relative;
}
#formeo-form .custom-file-label {
color: black;
cursor: pointer;
position: absolute;
top: 0;
left: 0;
height: 100%;
width: 30%;
display: flex;
align-items: center;
justify-content: center;
background-color: #F3F3F3;
border-right: 1px solid #cecece;
}
#formeo-form .custom-file-name {
position: absolute;
top: 0;
left: 30%;
height: 100%;
width: 70%;
padding: 0 1.5rem;
display: flex;
align-items: center;
}
#formeo-form .custom-file-name.placeholder {
color: #999;
}
#formeo-form .file-input:valid + .custom-file-label::after {
content: ' - ' attr(data-file-name);
}
@media only screen and (max-width: 768px) {
#formeo-form .formeo-row {
flex-direction: column;
padding: 0;
gap: 1em;
}
#formeo-form input[type="submit"].btn-blue {
display: block;
margin: 0 auto;
float: unset !important;
}
#formeo-form .formeo-column {
width: 100% !important;
padding: 0;
}
}
#formeo-form .error {
border-color: red !important;
}
#formeo-form select.error {
color: red;
}
#formeo-form .holder.error {
border-color: red;
}
/* To style radio & checkbox red if error */
#formeo-form input[type='radio'].error,
#formeo-form input[type='checkbox'].error {
visibility: hidden;
}
#formeo-form input[type='radio'].error:after,
#formeo-form input[type='checkbox'].error:after {
width: 0.5rem;
height: 0.5rem;
content: '';
display: inline-block;
visibility: visible;
border: 0.1rem solid red;
}
#formeo-form input[type='radio'].error:after {
border-radius: 0.5rem;
}
.contact_number_container {
position: relative;
}
.country_code_button {
position: absolute;
z-index: 10;
height: 100%;
display: flex;
align-items: center;
justify-content: flex-start;
width: 50px;
padding: 0 15px;
cursor: pointer;
background-image: url(images/dropdown-icon.png);
background-repeat: no-repeat;
background-position: right center;
background-size: 1rem;
}
.contact_number_container > input[type='tel'] {
padding-left: 100px !important;
}
.country_code_list {
display: none;
position: absolute;
top: 47px;
left: 0;
border: solid 1px #cecece;
max-height: 20rem;
overflow-x: auto;
cursor: pointer;
background-color: white;
z-index: 10;
}
.country_code_list > div {
display: flex;
align-items: center;
justify-content: flex-start;
padding: 0.5rem;
}
.country_code_list > div:hover {
background-color: lightgray;
}
#formeo-form .btn-wrapper {
position: relative;
display: inline-block;
float: right;
}
/* Loading state: hide text */
#formeo-form .btn-wrapper.loading input {
color: transparent; /* hide the button text */
pointer-events: none;
}
/* The spinner overlay */
#formeo-form .btn-wrapper.loading::after {
content: "";
position: absolute;
top: 50%;
left: 50%;
width: 20px;
height: 20px;
transform: translate(-50%, -50%);
border: 3px solid #f7a81b;
border-top-color: transparent;
border-radius: 50%;
animation: spin 0.8s linear infinite;
z-index: 2;
}
@keyframes spin {
to {
transform: translate(-50%, -50%) rotate(360deg);
}
}
Copy all related files to your project and import sql table
Create Form and Display:
Eg. I want to display 'Job Application Form'
<div id="formeo-form"><div class="wrapper"><?php $this->includeSnippet('render-form', ['form_name' => 'Job Application Form']) ?></div></div>
<div id="formeo-form"><div class="wrapper"><?php $this->includeSnippet('render-form', ['form_name' => 'Job Application Form']) ?></div></div>
If you want to adjust file upload limit, create a file '.user.ini' in same level folder as '.htaccess' and insert the code below, adjust your limit to your liking
upload_max_filesize = 25M
post_max_size = 25M
max_file_uploads = 25
upload_max_filesize = 25M
post_max_size = 25M
max_file_uploads = 25