Dropzone.js unable to map to viewmodel - html

I have the following drop zone js and have a file input hidden with an asp-for tag which should map to my viewmodel. However there is nothing being mapped. The controller accepts a parameter List FormFiles.
<form method="post" asp-action="Index" asp-controller="Customer" class="js-step-form js-validate" enctype="multipart/form-data"
data-hs-step-form-options='{
"progressSelector": "#validationFormProgress",
"stepsSelector": "#validationFormContent",
"endSelector": "#validationFormFinishBtn",
"isValidate": true
}'>
<!-- Step -->
<!-- End Step -->
<!-- Content Step Form -->
<div id="validationFormContent">
<div id="validationFormAccount" class="active">
<div class="row">
<div class="col-sm-6">
<!-- Form Group -->
<div class="form-group js-form-message mb-3">
<label class="input-label">Loyality Spend</label>
<input id="LoyalitySpendTextBox" type="text" class="form-control stringValidation" required
data-msg="Please enter Loyality Spend." placeholder="Loyality Spend" aria-label="Current Value" value="#Model.Customer.LoyaltySpend" asp-for="#Model.Customer.LoyaltySpend">
</div>
<!-- End Form Group -->
</div>
<div class="col-sm-6">
<!-- Form Group -->
<div class="form-group mb-3">
<label class="input-label">Documents</label>
<!-- Dropzone -->
<div id="attachFilesLabel" class="js-dropzone dropzone-custom custom-file-boxed">
<div class="dz-message dz-filename">
<img class="avatar avatar-xl avatar-4by3 mb-3" src="~/front-dashboard-v1.1/src/assets/svg/illustrations/browse.svg" alt="Image Description">
<h5>Drag and drop your file here</h5>
<p class="mb-2">or</p>
<span class="btn btn-sm btn-white" id="chose_files_btn" onclick="doOpen(event)">
Browse File
<input type="file" asp-for="#Model.FormFiles" id="File" name="File" size="1" style="display: none" />
</span>
</div>
</div>
<!-- End Dropzone -->
</div>
<!-- End Form Group -->
</div>
</div>
</div>
</form>

If you want to bind data with name FormFiles,you can use paramName of Dropzone.And if you want to upload files when button click,try to use autoProcessQueue: false,,and in button click event add e.preventDefault();wrapperThis.processQueue();.If you want to delete files,you need to add addRemoveLinks: true, and use removedfile. Here is a demo.
View:
<form asp-action="Upload" asp-antiforgery="false"
class="dropzone" id="myAwesomeDropzone" enctype="multipart/form-data">
<div class="fallback">
<input asp-for="FormFiles" type="file" multiple />
</div>
js:
<script src="https://cdnjs.cloudflare.com/ajax/libs/dropzone/5.9.2/dropzone.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/dropzone/5.9.2/dropzone.css"/>
<script>
function myParamName() {
return "FormFiles";
}
Dropzone.options.myAwesomeDropzone = {
autoProcessQueue: false,
paramName: myParamName, // The name that will be used to transfer the file
uploadMultiple: true,
parallelUploads: 100,
addRemoveLinks: true,
removedfile: function (file) {
file.previewElement.remove();
},
init: function () {
console.log("active");
var wrapperThis = this;
$("#submit").click(function (e) {
e.preventDefault();
wrapperThis.processQueue();
});
},
accept: function (file, done) {
done();
}
};
</script>
action:
[HttpPost]
public IActionResult Upload(List<IFormFile> FormFiles)
{
return Ok();
}
result:

Related

Is it possible to use the jquery validator in TinyMCE?

I'm trying to use jQuery no validator in a form that has a textarea using TinyMCE and I can't leave it as required.
I found some examples to make this requirement, but everyone I add ends up removing TinyMCE from my textarea.
Can anyone can help me? all examples are always giving error.
This is my code:
#model Contato
#{
ViewData["Title"] = "Contato nos";
Layout = "~/Views/Shared/_Layout.cshtml";
var end = "https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d14635.842857905212!2d-47.446606835918516!3d-23.49792447583607!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x94cf61e82bba04e5%3A0xec1214319ddea74d!2sMarcenaria%20MF!5e0!3m2!1spt-BR!2sbr!4v1620093541821!5m2!1spt-BR!2sbr";
}
<!-- ======= Breadcrumbs ======= -->
<section id="breadcrumbs" class="breadcrumbs">
<div class="container">
<div class="d-flex justify-content-between align-items-center">
<h2>Contato</h2>
<ol>
<li><a asp-controller="Home" asp-action="Index">Marcenaria MF</a></li>
<li>Contato</li>
</ol>
</div>
</div>
</section><!-- End Breadcrumbs -->
<!-- ======= Contact Section ======= -->
<div class="map-section">
<iframe style="border:0; width: 100%; height: 350px;" src=#end frameborder="0" allowfullscreen></iframe>
</div>
<section id="contact" class="contact">
<div class="container">
<div class="row justify-content-center" data-aos="fade-up">
<div class="col-lg-10">
<div class="info-wrap">
<div class="row">
<div class="col-lg-4 info">
<i class="bi bi-geo-alt"></i>
<h4>Endereço:</h4>
<p> R. Yashica, N° 350 - Jardim Bela Vista,<br>Sorocaba - SP, 18016-440</p>
</div>
<div class="col-lg-4 info mt-4 mt-lg-0">
<i class="bi bi-envelope"></i>
<h4>Email:</h4>
<p>info#example.com<br>contact#example.com</p>
</div>
<div class="col-lg-4 info mt-4 mt-lg-0">
<i class="bi bi-phone"></i>
<h4>Telefones:</h4>
<p>(15) 99756-6839<br>(15) 99761-6833</p>
</div>
</div>
</div>
</div>
</div>
<div class="row mt-5 justify-content-center" data-aos="fade-up">
<div class="col-lg-10">
<form id="form_contato" asp-controller="Contatos" asp-action="Contato" method="post" role="form" class="php-email-form" enctype="multipart/form-data">
<div class="row">
<div class="col-md-6 form-group">
<input type="text" name="Nome" class="form-control" asp-for="Nome" placeholder="Seu Nome">
<span asp-validation-for="Nome" class="text-danger"></span>
</div>
<div class="col-md-6 form-group mt-3 mt-md-0">
<input type="email" class="form-control" name="Email" asp-for="Email" placeholder="Seu Email">
<span asp-validation-for="Email" class="text-danger"></span>
</div>
</div>
<div class="form-group mt-3">
<input type="text" class="form-control" name="Assunto" asp-for="Assunto" placeholder="Assunto">
<span asp-validation-for="Assunto" class="text-danger"></span>
</div>
<div class="form-group mt-3">
<textarea class="form-control" name="Mensagem" rows="5" asp-for="Mensagem" placeholder="Mensagem"></textarea>
<span asp-validation-for="Mensagem" class="text-danger"></span>
</div>
<div class="my-3">
<div class="loading" id="loading">Loading</div>
<div class="error-message" id="error-message"></div>
<div class="sent-message" id="sent-message">Sua mensagem foi enviada. Obrigado!</div>
</div>
<div class="text-center"><button type="submit">Enviar Mensagem</button></div>
</form>
</div>
</div>
</div>
</section><!-- End Contact Section -->
<script src="~/tinymce/js/tinymce/tinymce.min.js"></script>
<script src="~/tinymce/langs/pt_BR.js"></script>
<script src="~/lib/jquery/dist/jquery.js"></script>
<script src="~/lib/jquery-validation/dist/jquery.validate.js"></script>
<script src="~/lib/jquery-validation/dist/additional-methods.js"></script>
<script src="~/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.js"></script>
<script>
$(document).ready(function () {
tinymce.init({
selector: 'textarea',
height: 250,
menubar: false,
plugins: 'link, autolink link, textcolor, paste',
toolbar: false,
content_css: '//www.tiny.cloud/css/codepen.min.css',
language: 'pt_BR',
paste_remove_styles_if_webkit: false,
paste_block_drop: false,
paste_data_images: false,
paste_as_text: true,
paste_enable_default_filters: false,
paste_webkit_styles: "none",
browser_spellcheck: true,
contextmenu: true,
branding: false,
statusbar: false,
setup: function (ed) {
//On change call
ed.on('change', function (e) {
//Validate tinyMCE on text change
tinyMCE.triggerSave();
$("#" + ed.id).valid();
}
);
},
});
$(function () {
$.validator.setDefaults({
submitHandler: function () {
$('#loading').addClass('d-block');
}
});
var content = tinyMCE.get("Mensagem");
tinyMCE.triggerSave();
//initialize validatoe
var validator = $("#form_contato").submit(function () {
// update underlying textarea before submit validation
alert($("#Mensagem").val());
}).validate({
ignore: ".ignore",
rules:
{
Email: {
required: true,
email: true,
},
Nome: {
required: true,
},
Assunto: {
required: true
},
Mensagem: {
required: true,
},
},
errorPlacement: function (label, element) {
// position error label after generated textarea
if (element.is("textarea")) {
label.insertAfter(element.next());
} else {
label.insertAfter(element)
}
}
});
validator.focusInvalid = function () {
// put focus on tinymce on submit validation
if (this.settings.focusInvalid) {
try {
var toFocus = $(this.findLastActive() || this.errorList.length && this.errorList[0].element || []);
if (toFocus.is("textarea")) {
tinyMCE.get(toFocus.attr("#Mensagem")).focus();
} else {
toFocus.filter(":visible").focus();
}
} catch (e) {
// ignore IE throwing errors when focusing hidden elements
}
}
}
})
});
</script>
#if (ViewData["MSG"] != null)
{
<script>
alert(#ViewData["MSG"].ToString());
</script>
}
I really appreciate your help guys

Get values of dynamic input fields

I have this HTML template:
<div class="container">
<div class="row">
<div class="col-md-12">
<div data-role="dynamic-fields">
<div class="form-inline">
<div class="form-group">
<label class="sr-only" for="field-name">Link </label>
<input type="text" class="form-control" id="field-name" placeholder="Link"
[(ngModel)]="HrefLink" name="HrefLink">
</div>
<span>-</span>
<div class="form-group">
<label class="sr-only" for="field-value">Label</label>
<input type="text" class="form-control" id="Label" placeholder="Label"
[(ngModel)]="HrefLabel" name="HrefLabel">
</div>
<button class="btn btn-danger" data-role="remove">
<span class="glyphicon glyphicon-remove"></span>
</button>
<button class="btn btn-primary" data-role="add">
<span class="glyphicon glyphicon-plus"></span>
</button>
</div> <!-- /div.form-inline -->
</div> <!-- /div[data-role="dynamic-fields"] -->
</div> <!-- /div.col-md-12 -->
</div> <!-- /div.row -->
</div>
In this simple form, I can add one or more inputs. This is the live example: https://bootsnipp.com/snippets/VPRlZ
My question is: How can I get the values of all added fields inside my angular component ? I can add the directive ngModel like above in every input but then all directives will have the same name and I'll not get all values?
Unfortunately, I can't place the ngModel in a higher level in the div of form-group ...
Please tell me if my question is clear or you need more information.
Why not you base the quantity of input in an array of Objects(InputModel it is a custom interface or class) and finally use *ngfor to show them.
InputModel
{
input_value: string,
index_of: number,
isDelete: boolean, //if false is "+" if true is "x"
}
Component.ts
inputValues: InputModel[] = [];
count: number = 0;
OnInit{
this.inputValues.push({
input_value:"",
index_of: this.count,
isDelete: true
});
}
addMore(){
this.inputValues.push({
input_value:"",
index_of: this.count++,
isDelete: false
});
}
Html Template
<div *ngFor="let input of inputValues">
<input [(ngModel)]="input.input_value" />
<!-- TODO button with 'x' or '+' depends of input.isDelete -->
</div>

How to show and hide <div>'s in Popover using AngularJS

I am working on SPA (Single Page Application) for Online Team Collaboration service(OTC) ,and I include HTML pages by ng-include,in some included page there is a popover ,this one contains a possibility for creating a public group chat,and in order to create one ,the user must submit, now my question is : how can i display a "successfully created" message in the same popover instead of the main div for creating the group in the popover?
The external page (the page that include other pages):
<div ng-show="ctrChanneldiv" ng-contoller="ctrChannelCon" style="float: right;" class="col-md-3">
<div ng-include="'CreateChannel.html'" ></div>
</div>
The Controller ctrChannelCon:
appvar.controller('ctrChannelCon',['$scope','$http','$rootScope',function($scope, $http, $rootScope){
$scope.createBtn = function() {
$http.post("http://localhost:8080/ExampleServletv3/crtchannelservlet",this.crtchannel)
.success(function(response) {
setTimeout(function () {
$scope.$apply(function(){
//******* Here Display "Successfully Created" In the Popover *******//
});
});
});
};
}]);
In CreateChannel.html :
<div>
<div class="row">
<a href="#" class="popper" data-toggle="popover"
data-placement="bottom"><span class="glyphicon glyphicon-plus"></span>Create Channel</a>
<div class="popper-content hide">
<div class="form-group">
<!-- ng-controller="createChannelCon" -->
<div class="form-group">
<label>Channel name:</label>
</div>
<div class="form-group">
<input ng-model="crtchannel.Name" type="text" placeholder="enter channel's name" maxlength="30"
class="form-control input-md" required />
</div>
<div class="form-group">
<label>Description:</label>
</div>
<div class="form-group">
<textarea cols="15" ng-model="crtchannel.Description" type="text"
placeholder="enter channel's description" maxlength="500"
class="form-control input-md" required></textarea>
</div>
<div>
<input ng-model="crtchannel.Type" type="radio" name="chtype"
value="private" required /> Private<br> <input
ng-model="crtchannel.Type" type="radio" name="chtype"
value="public" /> Public<br>
</div>
<div class="form-group">
<button ng-click="createBtn()" class="btn btn primary">Apply</button>
</div>
</div>
</div>
<script>
$('.popper').popover({
container : 'body',
html : true,
content : function() {
return $(this).next('.popper-content').html();
}
});
</script>
</div>
</div>
Any suggestions?
Thanks
You may use ngClass directive to counter this problem. ngClass directive allows conditional application of classes. Create a div for successfully created in the popup and set up ng-class directive with a variable in the scope and assign it true and false as per your requirement.
JS
appvar.controller('ctrChannelCon',['$scope','$http','$rootScope',function($scope, $http, $rootScope){
$scope.createBtn = function() {
$http.post("http://localhost:8080/ExampleServletv3/crtchannelservlet",this.crtchannel)
.success(function(response) {
setTimeout(function () {
$scope.$apply(function(){
//******* Change value of a model *******//
$scope.hidden = false;
});
});
});
};
}]);
HTML
<span ng-class="{hide: hidden}">Successfully Created</span>
CSS
.hide { display: none; }
Set a flag in your controller on success and use this flag to show or hide the success message:
...
<div class="form-group">
<button ng-click="createBtn()" class="btn btn primary">Apply</button>
</div>
<div ng-show="isSuccess">Successfully Created</div>
Inside the controller:
$scope.isSuccess = false;
$scope.createBtn = function() {
$http.post("http://localhost:8080/ExampleServletv3/crtchannelservlet",this.crtchannel)
.success(function(response) {
setTimeout(function () {
$scope.$apply(function(){
//******* Here Display "Successfully Created" In the Popover *******//
$scope.isSuccess = true;
});
});
});
};

knockout does not change the radio button view

I have a working panel with radio buttons a label and a textfield. Everything works good except if i click on radio buttons explicitly the radio button does not change the radio button view.
Here the plnkr link to it:
https://embed.plnkr.co/auD0sMEL88EsuaQqvt7E/
As #user3297291 mention that the checked and click binding get in confict.
Add this binding:
ko.bindingHandlers.stopBubble = {
init: function(element) {
ko.utils.registerEventHandler(element, "click", function(event) {
event.cancelBubble = true;
if (event.stopPropagation) {
event.stopPropagation();
}
});
}
};
You have to add in every radio element this binding like this:
<input data-bind="checked: discountValue, stopBubble: true" id="discountArbitrary" name="discount" type="radio" value="arbitrary" />
I created one jsfiddle that works as you expected.
https://jsfiddle.net/astrapi69/s3r60uLu/
I guess the click binding is conflicting with checked binding.
You can use computeds to calculate enabled/focused flags.
You can check modified code (I've omitted focused flags in favor of simplicity):
// Code goes here
var DiscountViewModel = function() {
var self = this;
self.arbitrary = ko.observable();
self.percent = ko.observable();
self.permanent = ko.observable();
self.discountValue = ko.observable('arbitrary');
self.enableArbitrary = ko.computed(() => self.discountValue() === 'arbitrary');
self.enablePercent = ko.computed(() => self.discountValue() === 'percent');
self.enablePermanent = ko.computed(() => self.discountValue() === 'permanent');
self.onArbitrary = onArbitrary;
self.onPercent = onPercent;
self.onPermanent = onPermanent;
function onArbitrary() {
self.discountValue('arbitrary');
}
function onPercent() {
self.discountValue('percent');
}
function onPermanent() {
self.discountValue('permanent');
}
};
var vm = new DiscountViewModel();
ko.applyBindings(vm);
/* Styles go here */
.header-line {
margin-bottom:20px;
margin-top:20px;
margin-left:20px;
}
<script data-require="jquery#2.1.3" data-semver="2.1.3" src="https://code.jquery.com/jquery-2.1.3.min.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/tether/1.3.3/js/tether.js"></script>
<link data-require="bootstrap#4.0.0-alpha.2" data-semver="4.0.0-alpha.2" rel="stylesheet" href="https://cdn.rawgit.com/twbs/bootstrap/v4-dev/dist/css/bootstrap.css" />
<script data-require="bootstrap#4.0.0-alpha.2" data-semver="4.0.0-alpha.2" src="https://cdn.rawgit.com/twbs/bootstrap/v4-dev/dist/js/bootstrap.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.0/knockout-debug.js"></script>
<link rel="stylesheet" href="style.css" />
<script src="script.js" type="text/javascript" defer="defer"></script>
<h1 class="header-line">
KO binding hasFocus over boolean values
</h1>
<div class="form-group row">
<div class="col-xs-1">
</div>
<div class="col-xs-1">
<input name="discount" type="radio" value="arbitrary" data-bind="checked: discountValue" />
</div>
<div class="col-xs-4">
<label for="arbitrary" data-bind="click: onArbitrary">Discount arbitrary</label>
</div>
<div class="col-xs-5">
<input type="text" class="form-control" id="arbitrary" placeholder="Enter arbitrary discount" data-bind="enable: enableArbitrary, value: arbitrary, hasFocus: enableArbitrary">
</div>
</div>
<div class="form-group row">
<div class="col-xs-1">
</div>
<div class="col-xs-1">
<input name="discount" type="radio" value="percent" data-bind="checked: discountValue" />
</div>
<div class="col-xs-4">
<label for="percent" data-bind="click: onPercent">Discount percent</label>
</div>
<div class="col-xs-5">
<input type="text" class="form-control" id="percent" placeholder="Enter percent of discount" data-bind="enable: enablePercent, value: percent, hasFocus: enablePercent">
</div>
</div>
<div class="form-group row">
<div class="col-xs-1">
</div>
<div class="col-xs-1">
<input name="discount" type="radio" value="permanent" data-bind="checked: discountValue" />
</div>
<div class="col-xs-4">
<label for="permanent" data-bind="click: onPermanent">Discount permanent</label>
</div>
<div class="col-xs-5">
<input type="text" class="form-control" id="permanent" placeholder="Enter permanent discount" data-bind="enable: enablePermanent, value: permanent, hasFocus: enablePermanent">
</div>
</div>
The problem is that by clicking the radio button, two things happen:
The checked binding does its thing
The event bubbles up to the parent element, and the click binding also does its thing.
You'll have to make sure clicking the input element stops the click binding from firing.
There's a great answer by R.P. Niemeyer here: https://stackoverflow.com/a/14321399/3297291

Phonegap save txt file of HTML form data

I need to use Phonegap to create an iOS app to save an HTML form. But, I'm not overly familiar with iOS or Phonegap. Can anyone point me in there correct direction?
Here is my HTML:
<!DOCTYPE html>
<html class="ipad" lang="en">
<head>
<meta charset="utf-8">
<title>Hall Render - Resources Sign Up</title>
<!-- Mobile Viewport -->
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
<!-- Main Stylesheet -->
<link href="assets/css/screen.css" media="all" rel="stylesheet" type="text/css">
<!-- jQuery -->
<script src="assets/js/jquery-1.11.3-min.js"></script>
<!-- jQuery Plugins -->
<script src="assets/js/jquery-validation-1.14.0-min.js"></script>
<!-- Phonegap JS -->
<script src="assets/js/phonegap.js"></script>
<script src="assets/js/cordova.js"></script>
<!-- Functions -->
<script src="assets/js/functions.js"></script>
</head>
<body onload="onDeviceReady()">
<!-- Begin Header -->
<header>
<div class="wrap">
<img src="assets/img/hall_render-logo.png" height="50" width="132">
<h1><strong>Health Law</strong> is our business.</h1>
</div>
</header>
<!-- End Header -->
<!-- Begin Secondary Header -->
<section id="secondary-header">
<div class="wrap">
<div class="inner-wrap">
<h2><strong>Hall Render Alerts Provide</strong> up-to-date information</h2>
<p>on topics ranging from general health law to health care reform, HIPAA,<br>
employment law, health information technology and health care tax news.</p>
</div>
</div>
</section>
<!-- End Secondary Header -->
<!-- Begin Main -->
<section id="main">
<div class="wrap">
<div class="inner-wrap">
<div class="text">
<h3>Sign Up to Receive Hall Render Resources</h3>
<p>
We appreciate your interest in our firm. As the nation’s largest law firm focused exclusively on matters specific to health care, our knowledge and experience allow us the opportunity to share the latest and most relevant health care news and practical takeaways directly with you. In an evolving industry such as health care, it’s crucial to stay up to date and informed. These email alerts are designed to help you do just that.
</p>
</div>
<form id="signup-form" method="get" action="">
<fieldset>
<div class="label-input-wrap">
<label for="cfirst-name">First Name: (required)</label>
<input type="text" id="cfirst-name" name="firstname" tabindex="1">
</div>
<div class="label-input-wrap">
<label for="clast-name">Last Name: (required)</label>
<input type="text" id="clast-name" name="lastname" tabindex="2">
</div>
<div class="label-input-wrap">
<label for="corganization">Organization:</label>
<input type="text" id="corganization" name="organization" tabindex="3">
</div>
<div class="label-input-wrap">
<label for="ctitle">Title:</label>
<input type="text" id="ctitle" name="title" tabindex="4">
</div>
<div class="label-input-wrap">
<label for="cemail">Email: (required)</label>
<input type="email" id="cemail" name="email" tabindex="5">
</div>
<input id="form-submit" type="submit" value="Sign Up" tabindex="6">
</fieldset>
</form>
</div>
</div>
</section>
<!-- End Main -->
<!-- Begin Secondary -->
<section id="secondary">
<div class="wrap">
<div class="inner-wrap">
<div class="text">
<h3>Thank You</h3>
<p>
Thank you for signing up to receive Hall Render resources.<br>
You will be receiving an email from us soon with the latest health law news.
</p>
</div>
</div>
</div>
</section>
<!-- End Secondary -->
<!-- Begin Footer -->
<footer>
<div id="red-tab"></div>
<div class="clear"></div>
<div id="red-banner"></div>
<div id="footer-hold">
<div class="wrap">
<p>
DENVER <span>|</span> DETROIT <span>|</span> INDIANAPOLIS <span>|</span> LOUISVILLE <span>|</span> MILWAUKEE <span>|</span> PHILADELPHIA <span>|</span> WASHINGTON, D.C.
</p>
</div>
</div>
</footer>
<!-- End Footer -->
</body>
</html>
Here is my functions.js file:
(function($){
/* On Page Ready */
$(document).ready(function(){});
/* On Page Load */
$(window).load(function(){
// Size differences
var mainH = $('#main').outerHeight();
var sheaH = $('#secondary-header').outerHeight();
$('#secondary').height(mainH + sheaH - 40).hide();
// Form Validation and Sumbit
var form = $('#signup-form');
form.validate({
debug: true,
rules: {
firstname: {
required: true
},
lastname: {
required: true
},
email: {
required: true,
email: true
}
},
messages: {
firstname: {
required: "Please enter your first name."
},
lastname: {
required: "Please enter your last name."
},
email: {
required: "Please enter your email."
}
},
submitHandler: function(form){
form.submit();
$('#main, #secondary-header').fadeOut(400);
$('#secondary').fadeIn(500);
setTimeout(function(){
window.location.reload(1);
}, 8000);
}
});
});
/* On Window Resize */
$(window).resize(function(){});
})(window.jQuery);
I'm using jQuery form validation and after validation it hides the form and shows a 'Thank You' and then reloads the page. Now, how do I get the form data to save to iOS file system? The app needs to be used offline and save info, reason why I need the info stored within iOS.
So I realized that I was going about this all WRONG. I needed the form data to post to a database. The database is used to collect all submitted form data. I believe the .txt file idea would be overwritten every single time the form data was submitted. So, I created two pages. One page to fill out and submit the form. One page to view all form entries and to export and clear database.
index.html
<head>
<meta charset="utf-8">
<title>Hall Render - Resources Sign Up</title>
<!-- Mobile Viewport -->
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
<!-- Main Stylesheet -->
<link href="assets/css/screen.css" media="all" rel="stylesheet" type="text/css">
<!-- jQuery -->
<script src="assets/js/jquery-1.11.3-min.js"></script>
<script src="assets/js/jquery.mobile-1.4.5.min.js"></script>
<!-- jQuery Plugins -->
<script src="assets/js/jquery-validation-1.14.0-min.js"></script>
<!-- Cordova JS -->
<script src="cordova.js"></script>
<!-- Functions -->
<script src="assets/js/functions.js"></script>
<script type="text/javascript">
document.addEventListener("deviceready", onDeviceReady, false);
function onDeviceReady(){
var db = window.openDatabase("HALLRENDER", 1.0, "App database",200000);
// Size differences
var mainH = $('#main').outerHeight();
var sheaH = $('#secondary-header').outerHeight();
$('#secondary').height(mainH + sheaH - 40).hide();
// Form Validation and Sumbit
var form = $('#signup-form');
form.validate({
debug: true,
rules: {
firstname: {
required: true
},
lastname: {
required: true
},
email: {
required: true,
email: true
}
},
messages: {
firstname: {
required: "Please enter your first name."
},
lastname: {
required: "Please enter your last name."
},
email: {
required: "Please enter your email."
}
},
submitHandler: function(form){
$('#main, #secondary-header').fadeOut(400);
$('#secondary').fadeIn(500);
db.transaction(populateDB, errorCB, successCB);
}
});
}
// Populate the database
function populateDB(tx) {
// Form Variables
var firstName = $('#cfirst-name').val();
var lastName = $('#clast-name').val();
var organization = $('#corganization').val();
var title = $('#ctitle').val();
var email = $('#cemail').val();
tx.executeSql('CREATE TABLE IF NOT EXISTS PEOPLE (Email, FirstName, LastName, Title, Organization)');
tx.executeSql('INSERT INTO PEOPLE (Email, FirstName, LastName, Title, Organization) VALUES ("'+email+'", "'+firstName+'", "'+lastName+'", "'+title+'", "'+organization+'")');
setTimeout(function(){
window.location.reload(1);
}, 8000);
}
// Transaction error callback
function errorCB(tx, err) {
alert("Error processing SQL: "+err);
}
// Transaction success callback
function successCB() {
console.log("Entry saved!");
}
</script>
</head>
<body onload="onDeviceReady()">
<!-- Begin Header -->
<header>
<div class="wrap">
<!-- SOMETHING -->
</div>
</header>
<!-- End Header -->
<!-- Begin Secondary Header -->
<section id="secondary-header">
<div class="wrap">
<div class="inner-wrap">
<!-- SOMETHING -->
</div>
</div>
</section>
<!-- End Secondary Header -->
<!-- Begin Main -->
<section id="main">
<div class="wrap">
<div class="inner-wrap">
<div class="text">
<!-- SOMETHING -->
</div>
<form id="signup-form">
<fieldset>
<div class="label-input-wrap">
<label for="cfirst-name">First Name: (required)</label>
<input type="text" id="cfirst-name" name="firstname" tabindex="1">
</div>
<div class="label-input-wrap">
<label for="clast-name">Last Name: (required)</label>
<input type="text" id="clast-name" name="lastname" tabindex="2">
</div>
<div class="label-input-wrap">
<label for="corganization">Organization:</label>
<input type="text" id="corganization" name="organization" tabindex="3">
</div>
<div class="label-input-wrap">
<label for="ctitle">Title:</label>
<input type="text" id="ctitle" name="title" tabindex="4">
</div>
<div class="label-input-wrap">
<label for="cemail">Email: (required)</label>
<input type="email" id="cemail" name="email" tabindex="5">
</div>
<input id="form-submit" type="submit" value="Sign Up" tabindex="6">
</fieldset>
</form>
</div>
</div>
</section>
<!-- End Main -->
<!-- Begin Secondary -->
<section id="secondary">
<div class="wrap">
<div class="inner-wrap">
<div class="text">
<h3>Thank You</h3>
</div>
</div>
</div>
</section>
<!-- End Secondary -->
</body>
export.html
<head>
<meta charset="utf-8">
<title>Hall Render - Export</title>
<!-- Mobile Viewport -->
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
<!-- Main Stylesheet -->
<link href="assets/css/screen.css" media="all" rel="stylesheet" type="text/css">
<!-- jQuery -->
<script src="assets/js/jquery-1.11.3-min.js"></script>
<!-- jQuery Plugins -->
<script src="assets/js/jquery-validation-1.14.0-min.js"></script>
<!-- Cordova JS -->
<script src="cordova.js"></script>
<!-- Functions -->
<script type="text/javascript">
document.addEventListener("deviceready", onDeviceReady, false);
function onDeviceReady(){
var db = window.openDatabase("HALLRENDER", 1.0, "App database",200000);
db.transaction(queryDB);
$('#dump').click(function(){
db.transaction(dropDB);
alert('Database Cleared!');
});
}
// Query Table Rows
function queryDB(tx) {
tx.executeSql('SELECT * FROM PEOPLE', [], querySuccess);
}
// Get Table Rows
function querySuccess(tx,result){
var status = document.getElementById("status");
var people = "";
var len = result.rows.length;
for (var i=0; i<len; i++){
people = people + '<li>'+result.rows.item(i).Email+','+result.rows.item(i).FirstName+','+result.rows.item(i).LastName+','+result.rows.item(i).Title+','+result.rows.item(i).Organization+'</li>';
}
status.innerHTML = people;
$("#status").listview("refresh");
}
// Delete Database
function dropDB(tx) {
tx.executeSql('DROP TABLE PEOPLE');
}
// File Writer
function saveCourseToFile() {
console.log("checkpoint 1");
window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, onFSSuccess, onFSError);
alert('CSV File Created!');
}
function onFSSuccess(fileSystem) {
console.log("checkpoint 2");
console.log("Opened file system: " + fileSystem.name);
fileSystem.root.getFile("export.csv", {create:true, exclusive:false}, gotFileEntry, onFSError);
}
function gotFileEntry(fileEntry) {
console.log("checkpoint 3");
fileEntry.createWriter(gotFileWriter, onFSError);
}
function gotFileWriter(writer) {
var entries = $('#status').find('li').filter(function() {
return $(this).find('ul').length === 0;
}).map(function(i, e) {
return $(this).text();
}).get().join('\n');
var dbEntries = 'Email,First Name,Last Name,Title,Organization\n'+entries;
writer.onwrite = function(evt) {
console.log("checkpoint 4: write success!");
};
writer.write(dbEntries);
}
function onFSError(err) {
console.log(err.code);
}
</script>
</head>
<body onload="onDeviceReady()">
<div class="inner-wrap">
<ol id="status" nam="status"></ol>
<div class="clear"></div>
<button id="export" onclick="saveCourseToFile()">Create .csv File Export</button>
<div class="clear"></div>
<button id="dump">Clear Database</button>
<p id="warning"><strong>WARNING: </strong>Export to .csv <em>BEFORE</em> clearing database!!</p>
<div class="clear"></div>
<div id="contents"></div>
</div>
</body>
This might look crazy. But, it works for what I was trying to accomplish. Take form data, save it locally, then export info into .csv file. Hopefully this gives someone else some insight into a similar problem. Thanks to everyone for helping!!
First install the cordova file plugin. http://docs.phonegap.com/en/edge/cordova_file_file.md.html
cordova plugin install org.apache.cordova.file
Capture the text from the form HTML with JQuery (#id).val() or document.getElementById('id').value.
Create the function to Write file like this:
My data captured from the form
var dataForm = $('#someId).val(); // All your text from the form.
Function for require File System and create file.
function createTxtFile(){
// Request File System
window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, function (fileSystem){
fileSystem.root.getFile("myTxt.txt", {create: true, exclusive: false},
function(fileEntry){
// Create File
fileEntry.createWriter(WriteText, fail);
}, fail);
},
fail
);
}
Function for write text.
function WriteText(writer) {
writer.onwriteend = function(evt){ // Fired when end write.
console.log("End write text in file");
};
writer.write(dataForm);
}