Do not want to submit form until email and phone are validated - Vue.js 3 - regex

I have a form that I am validating - all fields are required. Everything seems to be working except my form submits even when an incorrect phone and email are entered (according to my regex Watch validation). What do I seem to be missing to make sure that the default refresh is prevented if the email and phone are entered incorrectly?
First section is my html form, the second is my Vue.js 3 app code.
<form name="mainForm" #submit="submitForm" method="post">
<div class="row mb-3 gx-2">
<div class="col-md-6">
<label class="form-label aw-font-freight-medium mb-0"
>First Name*</label
>
<input
type="text"
name="firstname"
class="form-control aw-font-freight-medium aw-firstname"
v-model="contact.firstName"
required
/>
</div>
<div class="col-md-6">
<label class="form-label aw-font-freight-medium mb-0"
>Last Name*</label
>
<input
type="text"
name="lastname"
class="form-control aw-font-freight-medium"
v-model="contact.lastName"
required
/>
</div>
</div>
<div class="row mb-3">
<div class="col">
<label class="form-label aw-font-freight-medium mb-0"
>Email Address *</label
>
<input
type="text"
name="email"
class="form-control aw-font-freight-medium"
v-model="contact.email"
required
/>
<small class="form-text text-danger" v-if="msg.email"
>{{msg.email}}</small
>
</div>
</div>
<div class="row mb-3 gx-2">
<div class="col">
<label class="form-label aw-font-freight-medium mb-0"
>Phone*</label
>
<input
type="text"
name="phone"
class="form-control aw-font-freight-medium"
v-model="contact.phone"
required
/>
<small class="form-text text-danger" v-if="msg.phone"
>{{msg.phone}}</small
>
</div>
</div>
<a href="#" target="_blank">
<button type="submit" class="btn aw-bg-orange text-light">
<strong>Download</strong>
</button></a
>
<div>
<small class="form-text text-muted">
<em>* Denotes a required field.</em>
</small>
</div>
</form>
const app = Vue.createApp({
data() {
return {
currentYear: new Date().getFullYear(),
now: new Date().toISOString(),
isSubmitted: false,
msg: [],
contact: {
firstName: "##firstname##",
lastName: "##lastname##",
email: "##email##",
phone: "##phone##",
address: "##address##",
city: "##city##",
state: "##state##",
zip: "##zip##",
checked: false,
},
};
},
watch: {
contact: {
handler(newContact) {
this.validateEmail(newContact.email);
this.validatePhone(newContact.phone);
},
deep: true,
},
},
methods: {
submitForm(e) {
const isValid =
this.contact.firstName ||
this.contact.lastName ||
this.contact.email ||
this.contact.phone;
if (!isValid) {
e.preventDefault();
}
},
validateEmail(value) {
if (
/^[_a-zA-Z0-9-]+(\.[_a-zA-Z0-9-]+)*#[a-zA-Z0-9-]+(\.[a-zA-Z0-9-]+)*(\.[a-zA-Z]{2,20})$/.test(
value
)
) {
this.msg["email"] = "";
} else {
this.msg["email"] = "Please enter a valid email address.";
}
},
validatePhone(value) {
if (
/^[\+]?[(]?[0-9]{3}[)]?[-\s\.]?[0-9]{3}[-\s\.]?[0-9]{4,6}$/im.test(
value
)
) {
this.msg["phone"] = "";
} else {
this.msg["phone"] = "Please enter a valid, 10 digit phone number.";
}
},
},
});
app.mount("#awApp");

I think your isValid is not working as you expect
const isValid =
this.contact.firstName ||
this.contact.lastName ||
this.contact.email ||
this.contact.phone;
The value of isValid 👆 will return ##firstname##
You should use && instead of || to make sure all values are set. And you may want to include the validators.
You could do that by having validateEmail and validatePhone return a boolean and then you can do
submitForm(e) {
const isValid =
this.contact.firstName &&
this.contact.lastName &&
this.contact.email &&
this.contact.phone &&
this.validateEmail(this.contact.email) &&
this.validatePhone(this.contact.phone);
if (!isValid) {
e.preventDefault();
}
},
update
const app = Vue.createApp({
data() {
return {
currentYear: new Date().getFullYear(),
now: new Date().toISOString(),
isSubmitted: false,
msg: [],
contact: {
firstName: "##firstname##",
lastName: "##lastname##",
email: "##email##",
phone: "##phone##",
address: "##address##",
city: "##city##",
state: "##state##",
zip: "##zip##",
checked: false,
},
};
},
watch: {
contact: {
handler(newContact) {
this.validateEmail(newContact.email);
this.validatePhone(newContact.phone);
},
deep: true,
},
},
methods: {
submitForm(e) {
const isValid =
this.contact.firstName &&
this.contact.lastName &&
this.contact.email &&
this.contact.phone &&
this.validateEmail(this.contact.email) &&
this.validatePhone(this.contact.phone);
console.log(isValid)
if (!isValid) {
e.preventDefault();
}
},
validateEmail(value) {
if (
/^[_a-zA-Z0-9-]+(\.[_a-zA-Z0-9-]+)*#[a-zA-Z0-9-]+(\.[a-zA-Z0-9-]+)*(\.[a-zA-Z]{2,20})$/.test(
value
)
) {
this.msg["email"] = "";
return true
} else {
this.msg["email"] = "Please enter a valid email address.";
return false;
}
},
validatePhone(value) {
if (
/^[\+]?[(]?[0-9]{3}[)]?[-\s\.]?[0-9]{3}[-\s\.]?[0-9]{4,6}$/im.test(
value
)
) {
this.msg["phone"] = "";
return true
} else {
this.msg["phone"] = "Please enter a valid, 10 digit phone number.";
return false;
}
},
},
});
app.mount("#app");
<script src="https://unpkg.com/vue#3.0.11/dist/vue.global.prod.js"></script>
<div id="app">
<form name="mainForm" #submit="submitForm" method="post">
<div>
<div>
<label>First Name*</label>
<input
type="text"
name="firstname"
v-model="contact.firstName"
required
/>
</div>
<div>
<label>Last Name*</label>
<input
type="text"
name="lastname"
v-model="contact.lastName"
required
/>
</div>
</div>
<div>
<div>
<label>Email Address *</label>
<input type="text" name="email" v-model="contact.email" required />
<small v-if="msg.email">{{msg.email}}</small>
</div>
</div>
<div>
<div>
<label>Phone*</label>
<input type="text" name="phone" v-model="contact.phone" required />
<small v-if="msg.phone">{{msg.phone}}</small>
</div>
</div>
<a href="#" target="_blank">
<button type="submit">
<strong>Download</strong>
</button></a
>
<div>
<small>
<em>* Denotes a required field.</em>
</small>
</div>
</form>
</div>

Related

Django template is rendering in Multi-step form, but context data is not visible

I am working on this problem and somehow resolved it to a very great extent and almost everything is done. But the Django is rendering my template but not the Context.
I don't know why I have checked it by debugging and my context is rendering but not showing in frontend.
On this template, there is a form with 4 fieldset , I am submitting data in 1st fieldset and the dynamically show o/p accordingly on the second fieldset.
I am attaching screenshot to show what is rendering in template(2nd fieldset)
edit:
I have debugged this and in code all is working fine but it is not showing up in fornt-end, I dont know why
#views.py
def createQuotePage(request):
if request.method == "POST":
# Getting all the value
# saving in Table
saveInUnitsTable(-------some code, removed to shorten question ------)
saveInCustomerTable(-------some code, removed to shorten question ------)
saveInInquiryTable(-------some code, removed to shorten question ------)
flight_suggestions =Flight.objects.filter(sourceairportid=1,destinationairportid=51)
context = {'flight_suggestions':flight_suggestions,"test":"99999999999999999999999999999999999999"}
return render(request,"Freight/create_quote.html",context=context) # <-- here is the PROBLEM
if request.method == "GET":
print("========================GET=======================")
context = {'airport_data' : list(Airport.objects.all()),
'commodity_data':list(Commodity.objects.all()),
'customerType_data':list(Entity.objects.all()),
}
return render(request,"Freight/create_quote.html",context=context)
#scripts.js
(function($) {
"use strict";
$.backstretch;
$('#top-navbar-1').on('shown.bs.collapse', function(){
$.backstretch("resize");
});
$('#top-navbar-1').on('hidden.bs.collapse', function(){
$.backstretch("resize");
});
$('.f1 fieldset:first').fadeIn('slow');
$('.f1 .btn-next').on('click', function() {
//
var parent_fieldset = $(this).parents('fieldset');
var next_step = true;
var current_active_step = $(this).parents('.f1').find('.f1-step.active');
var progress_line = $(this).parents('.f1').find('.f1-progress-line');
//
var formData1 = $("#total-shipment-form").serialize();
var formData2 = $("#units-form").serialize();
var formData3 = $("#customerDetailForm").serialize();
var formData4 = $("#firstFieldset").serialize();
var formData = formData1 + '&' +
formData2 + '&' +
formData3 + '&' +
formData4
$.post("",formData)
.done(function(){
//
console.log('Success : ');
// var parent_fieldset = $(this).parents('fieldset');
// var next_step = true;
// var current_active_step = $(this).parents('.f1').find('.f1-step.active');
// var progress_line = $(this).parents('.f1').find('.f1-progress-line');
if( next_step ) {
parent_fieldset.fadeOut(400, function() {
current_active_step.removeClass('active').addClass('activated').next().addClass('active');
bar_progress(progress_line, 'right');
$(this).next().fadeIn();
scroll_to_class( $('.f1'), 20 );
});
}
//
})
.fail(function(){
console.log('Error : ');
});
});
Edited:-
Html template
<fieldset id="secondFieldset">
<div class="form-group select_all_style">
<input class="form-check-input" type="checkbox" value=""
id="select_all">
<label for="select_all" class="font-bold lh-26 fs-14">Select All</label>
</div>
{{test}}
<div class="airline_wrapper check_box_wrapper">
{{test}}
{% for flight in flight_suggestions %}
<div class="col_2 text-center dhl_text ">
<div class="aviation_wrapper">
<div class="aviation_checkbox">
<input class="form-check-input" type="checkbox" value=""
id="flexCheckDefault">
</div>
<div class="d-inline pl_10">
<!-- <p>Expiry Date <span><b>6 Sep 2022</b></span></p> -->
<h4 class="fw-400 fs-28">{{flight.flightcompany}}</h4>
<p>Air Freight</p>
</div>
</div>
</div>
<div class="col_6">
<div class="flight_container text-center">
<i class="fa-solid fa-plane plane_style"></i>
<div class="flight_details"></div>
<div class="flight_content">
<div>
<h4>{{flight.sourceairportid.airportname}}</h4>
<p>{{flight.sourceairportid.cityid.cityname}}</p>
</div>
<div>
<h4>{{flight.destinationairportid.airportname}}</h4>
<p>{{flight.destinationairportid.cityid.cityname}}</p>
</div>
</div>
<hr>
<div class="d-flex">
<div class="flight_sub_text text-left">
<label for="">Transit Time</label>
<h5>-- Hrs</h5>
<h5>{{flight.trasittime}} Hrs</h5>
</div>
</div>
</div>
</div>
<div class="col_3">
<h4 class="text-center reference_text">Past Reference</h4>
<div class="buy_text_wrapper">
<p>Buy Rate</p>
<p>Sell Rate</p>
</div>
<div class="buy_text_wrapper">
<p>USD 5,500.00</p>
<p>USD 7,000.00</p>
</div>
<h5 class="probabilty_text text-center pt-4"><span><i
class="fa-solid fa-arrow-trend-up"></i> 70%</span>
Winnning Probabilty</h5>
</div>
{% endfor %}
</div>
<div class="f1-buttons">
<button class="btn btn-primary btn-next" type="button">Request Better
Rates</button>
</div>
</fieldset>

PayPal API PopUp closes immediately after clicking PayPal button (Sandbox)

I am trying to implement the PayPal API into my Django / Vue checkout system, but everytime i try to access checkout via the paypal checkout buttons, thepopup closes immediately and i get these errors:
Error messages in developer tools
Obviously it has something to do with the cart's items' attributes and i tried to adjust them accordingly, but i can't figure out how to fix it. My Code:
<template>
<div class="page-checkout">
<div class="columns is-multiline">
<div class="column is-12">
<h1 class="title">Kasse</h1>
</div>
<div class="column is-12 box">
<table class="table is-fullwidth">
<thead>
<tr>
<th>Artikel</th>
<th>Preis</th>
<th>Anzahl</th>
<th>Gesamt</th>
</tr>
</thead>
<!-- vue for loop for looping through items in cart and displaying them in a table -->
<tbody>
<tr
v-for="item in cart.items"
v-bind:key="item.product.id"
>
<td>{{ item.product.name }}</td>
<td>{{ item.product.price }}€</td>
<td>{{ item.quantity }}</td>
<td>{{ getItemTotal(item).toFixed(2) }}€</td>
</tr>
</tbody>
<tfoot>
<tr style="font-weight: bolder; font-size: larger;">
<td colspan="2">Insgesamt</td>
<td>{{ cartTotalLength }}</td>
<td>{{ cartTotalPrice.toFixed(2) }}€</td>
</tr>
</tfoot>
</table>
</div>
<!-- Fields for user information -->
<div class="column is-12 box">
<h2 class="subtitle">Versanddetails</h2>
<p class="has-text-grey mb-4">*Felder müssen ausgefüllt sein</p>
<div class="columns is-multline">
<div class="column is-6">
<div class="field">
<label>*Vorname</label>
<div class="control">
<input type="text" class="input" v-model="first_name">
</div>
</div>
<div class="field">
<label>*Nachname</label>
<div class="control">
<input type="text" class="input" v-model="last_name">
</div>
</div>
<div class="field">
<label>*E-Mail</label>
<div class="control">
<input type="email" class="input" v-model="email">
</div>
</div>
<div class="field">
<label>*Telefonnummer</label>
<div class="control">
<input type="text" class="input" v-model="phone">
</div>
</div>
<div class="column is-6">
<div class="field">
<label>*Adresse</label>
<div class="control">
<input type="text" class="input" v-model="address">
</div>
</div>
<div class="field">
<label>*Postleitzahl</label>
<div class="control">
<input type="text" class="input" v-model="zipcode">
</div>
</div>
<div class="field">
<label>*Ort</label>
<div class="control">
<input type="text" class="input" v-model="place">
</div>
</div>
</div>
<!-- looping through errors for authorization -->
<div class="notification is-danger mt-4" v-if="errors.length">
<p v-for="error in errors" v-bind:key="error">{{ error }}</p>
</div>
<hr>
<div id="card-element" class="mb-5"></div>
<!-- Part for PayPal implementation -->
<template v-if="cartTotalLength">
<hr>
<!-- Set up a container element for the button -->
<div id="paypal-button-container"></div>
<!-- Include the PayPal JavaScript SDK -->
<div ref="paypal"></div>
<!-- <button class="button is-dark" #click="submitForm">Weiter mit PayPal</button> -->
</template>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import axios from 'axios'
export default {
name: 'Checkout',
data() {
return {
loaded: false,
paidFor: false,
cart: {
items: []
},
stripe: {},
card: {},
first_name: '',
last_name: '',
email: '',
phone: '',
address: '',
zipcode: '',
place: '',
errors: []
}
},
mounted() {
document.title = 'Kasse | RELOAD'
this.cart = this.$store.state.cart
// Imported PayPal functionality from https://fireship.io/lessons/paypal-checkout-frontend/
const script = document.createElement("script");
script.src = "https://www.paypal.com/sdk/js?client-id=AeAKmRDX7HTesdUvfqYqCQz3fZHIkjAoQ5-BG6K-7xnL5GBMVvwQba53v-I8Fx1p9wurUtoBuk7D6bV1"; // Replace YOUR-CLIENT-ID with paypal credentials
script.addEventListener("load", this.setLoaded);
document.body.appendChild(script); // Adds script to the document's body
},
watch: {
$route(to, from,) {
if (to.name === 'Category') {
this.getCategory()
}
}
},
methods: {
getItemTotal(item) {
return item.quantity * item.product.price
},
// Authorization methods
submitForm() {
this.errors = []
if (this.first_name === '') {
this.errors.push('Bitte Vornamen angeben')
}
if (this.last_name === '') {
this.errors.push('Bitte Nachnamen angeben')
}
if (this.email === '') {
this.errors.push('Bitte E-Mail angeben')
}
if (this.phone === '') {
this.errors.push('Bitte Telefonnummer angeben')
}
if (this.adress === '') {
this.errors.push('Bitte Adresse angeben')
}
if (this.zipcode === '') {
this.errors.push('Bitte Postleitzahl angeben')
}
if (this.place === '') {
this.errors.push('Bitte Ort angeben')
}
},
// Imported PayPal functionality from https://fireship.io/lessons/paypal-checkout-frontend/
setLoaded() {
this.loaded = true;
window.paypal
.Buttons({
// createOrder: (data, actions) => {
// return actions.order.create({
// purchase_units: [
// {
// description: this.product.description,
// amount: {
// currency_code: "EUR",
// value: this.product.price
// }
// }
// ]
createOrder: (data, actions) => {
return actions.order.create({
"purchase_units": [{
"amount": {
"currency_code": "EUR",
"value": item.product.price,
"breakdown": {
"item_total": { /* Required when including the items array */
"currency_code": "EUR",
"value": item.quantity * product.price
}
}
},
"items": [
{
"name": item.product.name, /* Shows within upper-right dropdown during payment approval */
"description": item.product.description, /* Item details will also be in the completed paypal.com transaction view */
"unit_amount": {
"currency_code": "EUR",
"value": item.product.price
},
"quantity": item.product.quantity
},
]
}]
});
},
onApprove: async (data, actions) => {
const order = await actions.order.capture();
this.paidFor = true;
console.log(order);
},
onError: err => {
console.log(err);
}
})
.render(this.$refs.paypal);
}
},
computed: {
// Computing total price and total amount of all items
cartTotalPrice() {
return this.cart.items.reduce((acc, curVal) => {
return acc += curVal.product.price * curVal.quantity
}, 0)
},
cartTotalLength() {
return this.cart.items.reduce((acc, curVal) => {
return acc += curVal.quantity
}, 0)
}
}
}
</script>
The createOrder function inside setLoaded() is assigning properties using item although it's not clear where item comes from as it's not being passed in from anywhere:
setLoaded() {
this.loaded = true;
window.paypal.Buttons({
createOrder: (data, actions) => {
return actions.order.create({
purchase_units: [
{
amount: {
currency_code: "EUR",
value: item.product.price, // <--- item is not defined here
breakdown: {
item_total: {
currency_code: "EUR",
value: item.quantity * product.price, // <--- or here
},
},
},
...
If you mean to reference the items in the cart data property you need to use this.cart.items and possibly loop through it if you're trying to send individual item details.

I'm using Angular 1.6 with django, if i refresh a page django serves the html file but controllers are not loading

I'm sharing my main.js, controller.js, home_page.html, index.html file below. Please some one help me fix the issue which is, when i was in the home page ('127.0.0.1:8000/home/') and try to refresh the page im getting only the html page and all the contents in the rootScope or scope disappears. But this is usual but i don't know how to again gain the data from the controller.
main.js
$stateProvider
.state("base", {
url : "/",
views : {
"main-content" : {
controller : "baseController",
template : "<div ui-view='content'></div>"
}
}
})
.state("base.login", {
url : "account/login/",
views : {
"content" : {
controller : "loginController",
templateUrl : "/account/login/"
}
}
})
.state("base.register", {
url : "account/register/",
views : {
"content" : {
controller : "registerController",
templateUrl : "/account/register/"
}
}
})
.state("base.home", {
url : "home/",
views : {
"content" : {
controller : "homeController",
templateUrl : "/home/"
}
}
})
.state("base.changepassword", {
url : "settings/",
views : {
"content" : {
controller : "changePasswordController",
templateUrl : "/settings/"
}
}
})
controller.js
myApp.controller('homeController', ['$http', '$scope', '$window', '$rootScope', function($http, $scope, $window, $rootScope) {
// debugger;
if (! $rootScope.currentUser.first_name) {
var search_payload = {
"email": $rootScope.currentUser.email
};
$http({
url: '/api/current/user/',
method: "POST",
data : search_payload,
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
}
}).then(function(response) {
$rootScope.currentUser = response.data;
console.log("Current User - ", $rootScope.currentUser);
});
}
$scope.clear_cookie = function ($event) {
$event.preventDefault();
console.log("Clear Cookie");
var cookies = document.cookie.split(';');
for (var i = 0; i < cookies.length; i++) {
var cookie = cookies[i];
var eqPos = cookie.indexOf("=");
var name = eqPos > -1 ? cookie.substr(0, eqPos) : cookie;
document.cookie = name + "=;expires=Thu, 21 Jun 2018 12:00:00 GMT";
}
$http({
url: '/api/logout/',
method: "POST",
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
}
}).then(function(response) {
console.log(response);
if (response.data.status == 'success') {
window.location = '/';
}
});
};
$scope.submit = function ($event, currentUser, isValid) {
$event.preventDefault();
if (isValid) {
var search_payload = {
"update": "true",
"username": currentUser.username,
"first_name": currentUser.first_name,
"last_name": currentUser.last_name,
"age": currentUser.age,
"email": currentUser.email,
"mobile": currentUser.mobile,
"address": currentUser.address
};
console.log(search_payload);
$http({
url: '/api/current/user/',
method: "POST",
data : search_payload,
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
}
}).then(function(response) {
$rootScope.currentUser = response.data;
console.log("Current User - ", $rootScope.currentUser);
if(response.data.status == 'success') {
swal({
title: "Success",
text: "Successfully updated your profile.",
icon: "success",
button: "Okay!",
});
} else {
swal({
title: "Failed",
text: "Something went wrong sorry please try again after sometime.",
icon: "error",
button: "Okay!",
});
}
});
} else {
swal({
title: "Failed",
text: "Please correct the errors and submit the form.",
icon: "error",
button: "Okay!",
});
}
}
}]);
home_page.html
<div class="login_form_class" ng-if="currentUser.username">
<form name="updateForm">
{% csrf_token %}
<div name="login_form" class="login_form col-md-4">
<div class="header">PROFILE</div>
<hr/>
<label class="input_label col-md-5" for="username">USERNAME</label>
<input class="input_box col-md-7" type="text" id="username" name="username" ng-init="username='{$ currentUser.username $}'" ng-model="currentUser.username" placeholder="{$ currentUser.username $}" value="{$ currentUser.username $}" pattern="[a-zA-Z0-9]+"/>
<div role="alert">
<span class="error error_msg pull-right" ng-show="updateForm.username.$error.pattern">Must contain only alphanumeric Special characters are not allowed</span>
</div>
<br/>
<label class="input_label col-md-5" for="first_name">FIRST NAME</label>
<input class="input_box col-md-7" type="text" id="first_name" name="first_name" ng-init="first_name='{$ currentUser.first_name $}'" ng-model="currentUser.first_name" placeholder="{$ currentUser.first_name $}" value="{$ currentUser.first_name $}" pattern="[A-Za-z]+"/>
<div role="alert">
<span class="error error_msg pull-right" ng-show="updateForm.first_name.$error.pattern">Must contain only alphabets</span>
</div>
<br/>
<label class="input_label col-md-5" for="last_name">LAST NAME</label>
<input class="input_box col-md-7" type="text" id="last_name" name="last_name" ng-init="last_name='{$ currentUser.last_name $}'" ng-model="currentUser.last_name" placeholder="{$ currentUser.last_name $}" value="{$ currentUser.last_name $}" pattern="[a-zA-Z]+"/>
<div role="alert">
<span class="error error_msg pull-right" ng-show="updateForm.last_name.$error.pattern">Must contain only alphabets</span>
</div>
<br/>
<label class="input_label col-md-5" for="age">AGE</label>
<input class="input_box col-md-7" type="text" id="age" name="age" ng-init="age='{$ currentUser.age $}'" ng-model="currentUser.age" placeholder="{$ currentUser.age $}" value="{$ currentUser.age $}" ng-minlength="2" ng-maxlength="2" pattern="[0-9]{2}"/>
<div role="alert">
<span class="error error_msg pull-right" ng-show="updateForm.age.$error.minlength">Must have a number</span>
<span class="error error_msg pull-right" ng-show="updateForm.age.$error.maxlength">Must be two digit</span>
<span class="error error_msg pull-right" ng-show="updateForm.age.$error.pattern">Must be an integer</span>
</div>
<br/>
<label class="input_label col-md-5" for="email">EMAIL</label>
<input class="input_box col-md-7" type="email" id="email" ng-init="email='{$ currentUser.email $}'" ng-model="currentUser.email" placeholder="{$ currentUser.email $}" value="{$ currentUser.email $}" disabled/>
<br/>
<label class="input_label col-md-5" for="mobile">MOBILE</label>
<input class="input_box col-md-7" type="text" id="mobile" name="mobile" ng-init="mobile='{$ currentUser.mobile $}'" ng-model="currentUser.mobile" placeholder="{$ currentUser.mobile $}" value="{$ currentUser.mobile $}" ng-minlength="10" ng-maxlength="10" pattern="[0-9]{10}" />
<div role="alert">
<span class="error error_msg pull-right" ng-show="updateForm.mobile.$error.minlength">Must contain 10 digits</span>
<span class="error error_msg pull-right" ng-show="updateForm.mobile.$error.maxlength">Must contain only 10 digits</span>
<span class="error error_msg pull-right" ng-show="updateForm.mobile.$error.pattern">Must contain only numbers</span>
</div>
<br/>
<label class="input_label col-md-5" for="address">ADDRESS</label>
<textarea class="input_box col-md-7" id="address" ng-init="address='{$ currentUser.address $}'" ng-model="currentUser.address" placeholder="{$ currentUser.address $}">{$ currentUser.address $}</textarea>
<br/>
<button type="submit" class="btn btn-info update_btn" ng-click="submit($event, currentUser, updateForm.$valid)">SAVE CHANGES</button>
</div>
</form>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.min.js"></script>
<script>
var cookie = document.cookie.split('=')[1];
var search_payload = {
"email": cookie.split(';')[0]
};
var promise = $.ajax({
url: '/api/current/user/',
method: 'POST',
data: search_payload
});
promise.done(function(response) {
// $rootScope.currentUser = response;
console.log(response);
});
</script>
</div>
index.html
<!DOCTYPE html>
<html ng-app="myApp">
<body>
<div class="content_panel" ui-view="main-content"></div>
</body>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.5/angular.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.5/angular-animate.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.5/angular-aria.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.5/angular-messages.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-material/1.1.6/angular-material.min.js"></script>
<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
<script src="https://cdn.jsdelivr.net/npm/js-cookie#2/src/js.cookie.min.js"></script>
<script src="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-router/1.0.18/angular-ui-router.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.5/angular-route.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.5/angular-resource.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.5/angular-sanitize.min.js"></script>
<script src="https://unpkg.com/sweetalert/dist/sweetalert.min.js"></script>
<script>
var csrftoken = Cookies.get('csrftoken');
var myApp = angular.module('myApp', ['ngRoute', 'ngResource', 'ngMaterial', 'ngMessages', 'ngSanitize', 'ui.router']);
</script>
<script src="{% static 'main.js' %}"></script>
<script src="{% static 'controllers.js' %}"></script>
</html>

Call google.script.run from HTMLService Template

When i try execute comand
var obj = google.script.run.receitaws(cnpj);
from custom html template form didin't work, return Undefined, but when run this function by spreadsheets work's.
I will post my project below:
I combine many html files to create html struture form.
To join files i use the function include(file)
function include(File) {
var template = HtmlService.createTemplateFromFile(File).evaluate();
Logger.log(template.getContent());
return HtmlService.createHtmlOutput(template.getContent()).getContent();
}
To call my custom html template by function openlink
function openlink() {
var template = HtmlService.createTemplateFromFile('tabs')
.evaluate()
.setSandboxMode(HtmlService.SandboxMode.IFRAME)
.setWidth(650);
SpreadsheetApp.getUi() // Or DocumentApp or FormApp.
.showModalDialog(template, 'Form');
}
File tabs is a html template file
<?!= include('before')?>
<ul id="tabs-form-servico" class="tabs">
<li id="tbulli1" class="tab col s2"><a class="" href="#tab1">1 - Tomador do Serviço</a></li>
<li id="tbulli2" class="tab col s2"><a class="active" href="#tab2">2 - Prestador do Serviço</a></li>
<li id="tbulli3" class="tab col s2 hide">3 - Serviço Executado</li>
<li id="tbulli4" class="tab col s2 hide">4 - Regras Retenção Municipal</li>
<li id="tbulli5" class="tab col s2 hide">5 - Regras Retenção Previdenciario</li>
<li id="tbulli6" class="tab col s2 hide">6 - Regras Retenções Federal</li>
<li id="tbulli7" class="tab col s2 hide">7 - Cálculo Retenções</li>
<li id="tbulli8" class="tab col s2 hide">8 - Pagamento</li>
</ul>
<div id="tab1" class="col s12">Criar</div>
<div id="tab2" class="col s12"><?!= include('prestadorservico')?></div>
<div id="tab3" class="col s12">Teste bem sucedido</div>
<div id="tab4" class="col s12"></div>
<div id="tab5" class="col s12"></div>
<div id="tab6" class="col s12"></div>
<div id="tab7" class="col s12"></div>
<div id="tab8" class="col s12"></div>
<script>
$(document).ready(function(){
$('#tabs-form-servico').tabs({'swipeable': true });
Materialize.updateTextFields();
});
function close() {
google.script.host.close()'
}
</script>
<?!= include('after')?>
File before is a html template file also
<!DOCTYPE html>
<html>
<head>
<base target="_blank">
<!--Import Google Icon Font-->
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
<!--Import materialize.css-->
<link type="text/css" rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.100.2/css/materialize.min.css" media="screen,projection">
<!--Let browser know website is optimized for mobile-->
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
</head>
<body>
File after is a html template file also
<script type="text/javascript" src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.100.2/js/materialize.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery.mask/1.14.10/jquery.mask.min.js"> </script>
<script>
$(document).ready(function() {
$('select').material_select();
$('.tooltipped').tooltip({delay: 50});
});
</script>
</body>
</html>
The problem is here in html template file prestadorservico
<div class="row">
<form class="col s12">
<div class="row">
<div class="input-field col s3">
<input id="cnpj" type="text" class="validate" autofocus>
<label for="cnpj">CNPJ</label>
</div>
<div class="input-field col s1">
<a class="btn-floating tooltipped rounded" onclick="consultacnpj()" data-tooltip="Preenchimento Automático da RF"><i class="material-icons">refresh</i></a>
</div>
<div class="input-field col s8">
<input placeholder="Prestador LTDA" id="contratado_nome" type="text" class="validate">
<label for="contratado_nome">Nome do Contratado</label>
</div>
</div>
<div class="row">
<div class="input-field col s10">
<input value="" id="address" type="text" class="validate">
<label for="address">Endereço</label>
</div>
<div class="input-field col s2">
<input value="" id="number" type="text" class="validate">
<label for="number">Número</label>
</div>
</div>
<div class="row">
<div class="input-field col s6">
<input value="" id="compl" type="text" class="validate">
<label for="compl">Complemento</label>
</div>
<div class="input-field col s6">
<input value="" id="bairro" type="text" class="validate">
<label for="bairro">Bairro</label>
</div>
</div>
<div class="row">
<div class="input-field col s6">
<?!= include('cidades');?>
</div>
<div class="input-field col s6">
<input value="" id="cep" type="text" class="validate">
<label for="cep">CEP</label>
</div>
</div>
<div class="row">
<div class="input-field col s7">
<input id="email" type="email" class="validate">
<label for="email" data-error="wrong" data-success="right">Email</label>
</div>
<div class="input-field col s5">
<input id="phone" type="text" class="validate">
<label for="phone">Telefone</label>
</div>
</div>
<div class="row">
<div class="input-field col s12 m6">
<input value="" id="cnaep" type="text" class="validate">
<label for="cnaep">CNAE Principal</label>
</div>
<div class="input-field col s12 m6">
<input value="" id="cnaes" type="text" class="validate">
<label for="cnaes">CNAE Secundários</label>
</div>
</div>
<div class="row">
<div class="input-field col s6">
<select>
<option value="" disabled selected>Escolha sua opção</option>
<option value="1">Pessoa Física</option>
<option value="2">MEI - Micro Empreendedor Individual</option>
<option value="3">Imunes/Isentas</option>
<option value="4">Cooperativa de Trabalho</option>
<option value="5">Simples Nacional</option>
<option value="6">Lucro Real/Presumido</option>
</select>
<label>Regime Tributário</label>
</div>
<div class="container col s3 offset-s3">
<a class="btn-large waves-effect waves-light right" id="btnnext2" onclick="nextstep()" name="next">Next
<i class="material-icons right">send</i>
</a>
</div>
</div>
</form>
</div>
<div class="divider"> </div>
<?!= include('SimplesReceitaFederal')?>
<script>
function nextstep() {
$('#tbulli3').removeClass('hide');
$('#tabs-form-servico').tabs('select_tab', 'tab3');
}
function consultacnpj(){
var cnpj = $('#cnpj').val().toString();
if (cnpj.length==14){
var obj = google.script.run.receitaws(cnpj); //here i have a problem
$('#contratado_nome').val(obj);
$('#address').val(obj.logradouro);
$('#number').val(obj.numero);
$('#compl').val(obj.complemento);
$('#bairro').val(obj.bairro);
$('#cep').val(obj.cep);
$('#city').val((obj.municipio + '/' + obj.uf))
var code = google.script.run.codeCNAE(obj.atividade_principal[0].code);
$('#cnaep').val((code + ' - ' + obj.atividade_principal[0].text));
var codes = google.script.run.CNAESecundarios(obj.atividades_secundarias);
$('#cnaes').val(codes);
} else {
Materialize.toast('Preencha um CNPJ valido.', 3000)
}
}
</script>
File cidades is a html template file
<? var data = SpreadsheetApp
.openById('my_id_Sheet')
.getSheetByName('Municipios')
.getRange(3, 4, 5575)
.getValues(); ?>
<select>
<option value="" disabled selected>Escolha a Cidade/UF</option>
<? for (var i = 0; i < data.length; i++) { ?>
<option value="<?!= i ?>"><?!= data[i] ?></option>
<? } ?>
</select>
<label>Cidade/UF</label>
Function.gs codeCNAE()
function codeCNAE(cod){
cod = cod.replace('.', '');
var cods = cod.split('-');
cod = cods[0]+'-'+cods[1]+'/'+cods[2];
return cod;
}
Function.gs CNAESecundarios()
function CNAESecundarios(obj){
var i, codes = "";
for (i in obj) {
if (codes == '') {
codes = '{' + codeCNAE(obj[i].code)
} else {
codes = codes + ', ' + codeCNAE(obj[i].code)
}
codes = codes + ' - ' + obj[i].text
}
codes = codes + '}'
//Logger.log(codes);
return codes;
}
Function.gs receitaws()
function receitaws(cnpj) {
Utilities.sleep(Math.random() * 1000);
var token = "my_id_token";
var url, response, obj;
url = 'http://receitaws.com.br/v1/cnpj/'
+ cnpj;
response = UrlFetchApp.fetch(url, {'muteHttpExceptions': true});
obj = JSON.parse(response);
if (obj.status == "ERROR" && obj.message !="CNPJ inválido") {
Logger.log('Versão Paga');
url = 'https://receitaws.com.br/v1/cnpj/'
+ cnpj
+ "/days/0";
response = UrlFetchApp.fetch(url, {'muteHttpExceptions': true, 'headers': {'Authorization': 'Bearer ' + token}});
obj = JSON.parse(response);
}
return obj;
}
I discovered my problem. In this case I need to run a
.withSuccessHandler(onSuccess)
to get a function return called.
I tried this and it worked.
I change my function consultacnpj() in file prestadorservico
function consultacnpj(){
var cnpj = $('#cnpj').val().toString();
if (cnpj.length==14){
google.script.run
.withSuccessHandler(onSuccessCNPJ)
.withFailureHandler(onFailureCNPJ)
.receitaws(cnpj);
function onFailureCNPJ(error) {
Materialize.toast("ERROR: " + error.message, 3000)
}
function onSuccessCNPJ(obj) {
$('#contratado_nome').val(obj.nome);
$('#address').val(obj.logradouro);
$('#number').val(obj.numero);
$('#compl').val(obj.complemento);
$('#bairro').val(obj.bairro);
$('#cep').val(obj.cep);
$('#city').val((obj.municipio + '/' + obj.uf))
var code = google.script.run
.withSuccessHandler(onSuccessCNAEP)
.withFailureHandler(onFailureCNAEP)
.codeCNAE(obj.atividade_principal[0].code);
function onFailureCNAEP(error) {
Materialize.toast("ERROR: " + error.message, 3000)
}
function onSuccessCNAEP(code) {
$('#cnaep').val(code + ' - ' + obj.atividade_principal[0].text);
};
google.script.run
.withSuccessHandler(onSuccessCNAES)
.withFailureHandler(onFailureCNAES)
.CNAESecundarios(obj.atividades_secundarias);
function onFailureCNAES(error) {
Materialize.toast("ERROR: " + error.message, 3000)
}
function onSuccessCNAES(codes) {
$('#cnaes').val(codes);
}
Materialize.updateTextFields();
Materialize.updateTextFields();
}
} else {
Materialize.toast('Preencha um CNPJ valido.', 3000)
}
}
If anyone have a other tip, please post it.
I'm still learning google-apps-script and javascript.
Thanks!

Install Opencart store in subdirectory with a Login in the root folder

hope all is well. I am trying to install Opencart (2.0.3) into a subdirectory (Ie. www.website.com/shop/) I want the root URL www.website.com to go to a Login page, where once a user logs in. It will redirect them to the /shop/ portion of the site and allow them to continue their business. I was wondering what the easiest way was to accomplish this. Would I install everything in the root folder, and then modify the .htaccess file along with the config files? Then how would i Make the login files work in the root folder? I tried installing everything first into the subdirectory /shop/... but then I get issues trying to figure out how to get files in the root folder to work.
Thanks in advance!
Yes, need to work with ajax functionality as below. In the index.php insert the following code and replace URL_WITH_SHOP with your urlshop. Then I have taken "shop" as sub-folder installation if it is different then replace "shop" with your sub-folder name:
<script src="shop/catalog/view/javascript/jquery/jquery-2.1.1.min.js" type="text/javascript"></script>
<script src="shop/catalog/view/javascript/bootstrap/js/bootstrap.min.js" type="text/javascript"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
<div class="container">
<div class="row">
<div id="content" class="col-sm-12 ">
<div class="row ">
<div class="col-sm-6" style="margin: 0px auto; float: none;">
<div class="well">
<h2>Returning Customer</h2>
<p><strong>I am a returning customer</strong></p>
<form method="post" enctype="multipart/form-data">
<div class="error"></div>
<div class="form-group">
<label class="control-label" for="input-email">E-Mail Address</label>
<input type="text" name="email" value="" placeholder="E-Mail Address" id="input-email" class="form-control" />
</div>
<div class="form-group">
<label class="control-label" for="input-password">Password</label>
<input type="password" name="password" value="" placeholder="Password" id="input-password" class="form-control" />
</div>
<button type="button" id="button-cart" data-loading-text="Checking login" class="btn btn-primary ">Login</button>
</form>
</div>
</div>
</div>
</div>
</div>
</div>
<script type="text/javascript"><!--
$('#button-cart').on('click', function() {
$.ajax({
url: 'shop/index.php?route=account/loginajax',
type: 'post',
data: $('input[type=\'text\'], input[type=\'password\']'),
dataType: 'json',
beforeSend: function() {
$('#button-cart').button('loading');
},
complete: function() {
$('#button-cart').button('reset');
},
success: function(json) {
$('.alert, .text-danger').remove();
$('.form-group').removeClass('has-error');
if (json['error']) {
$('.error').after('<div class="alert alert-danger has-error">' + json['error'] + '</div>');
}
if (json['success']) {
$('.error').after('<div class="alert alert-success">' + json['success'] + '</div>');
window.location = "URL_WITH_SHOP";
}
}
});
});
//--></script>
Above is the presentation layer, now let's make the logical layer, go to shop/catalog/controller/account and create loginajax.php and paste following code:
<?php
class ControllerAccountLoginAjax extends Controller
{
private $error = array();
public function index()
{
$this->load->model('account/customer');
$json = array();
// Login override for admin users
if (!empty($this->request->get['token'])) {
$this->event->trigger('pre.customer.login');
$this->customer->logout();
$this->cart->clear();
unset($this->session->data['wishlist']);
unset($this->session->data['payment_address']);
unset($this->session->data['payment_method']);
unset($this->session->data['payment_methods']);
unset($this->session->data['shipping_address']);
unset($this->session->data['shipping_method']);
unset($this->session->data['shipping_methods']);
unset($this->session->data['comment']);
unset($this->session->data['order_id']);
unset($this->session->data['coupon']);
unset($this->session->data['reward']);
unset($this->session->data['voucher']);
unset($this->session->data['vouchers']);
$customer_info = $this->model_account_customer->getCustomerByToken($this->request->get['token']);
if ($customer_info && $this->customer->login($customer_info['email'], '', true)) {
// Default Addresses
$this->load->model('account/address');
if ($this->config->get('config_tax_customer') == 'payment') {
$this->session->data['payment_address'] = $this->model_account_address->getAddress($this->customer->getAddressId());
}
if ($this->config->get('config_tax_customer') == 'shipping') {
$this->session->data['shipping_address'] = $this->model_account_address->getAddress($this->customer->getAddressId());
}
$this->event->trigger('post.customer.login');
$this->response->redirect($this->url->link('account/account', '', 'SSL'));
}
}
if ($this->customer->isLogged()) {
$this->response->redirect($this->url->link('account/account', '', 'SSL'));
}
if (!$json) {
$this->load->language('account/login');
$this->document->setTitle($this->language->get('heading_title'));
if (($this->request->server['REQUEST_METHOD'] == 'POST') && $this->validate()) {
$json['success'] = "Successfully logging in! ";
unset($this->session->data['guest']);
// Default Shipping Address
$this->load->model('account/address');
if ($this->config->get('config_tax_customer') == 'payment') {
$this->session->data['payment_address'] = $this->model_account_address->getAddress($this->customer->getAddressId());
}
if ($this->config->get('config_tax_customer') == 'shipping') {
$this->session->data['shipping_address'] = $this->model_account_address->getAddress($this->customer->getAddressId());
}
// Add to activity log
$this->load->model('account/activity');
$activity_data = array(
'customer_id' => $this->customer->getId(),
'name' => $this->customer->getFirstName() . ' ' . $this->customer->getLastName()
);
$this->model_account_activity->addActivity('login', $activity_data);
}
else{
$json['error'] = $this->language->get('error_login');
}
$data['breadcrumbs'] = array();
$data['breadcrumbs'][] = array(
'text' => $this->language->get('text_home'),
'href' => $this->url->link('common/home')
);
$data['breadcrumbs'][] = array(
'text' => $this->language->get('text_account'),
'href' => $this->url->link('account/account', '', 'SSL')
);
$data['breadcrumbs'][] = array(
'text' => $this->language->get('text_login'),
'href' => $this->url->link('account/login', '', 'SSL')
);
$data['heading_title'] = $this->language->get('heading_title');
$data['text_new_customer'] = $this->language->get('text_new_customer');
$data['text_register'] = $this->language->get('text_register');
$data['text_register_account'] = $this->language->get('text_register_account');
$data['text_returning_customer'] = $this->language->get('text_returning_customer');
$data['text_i_am_returning_customer'] = $this->language->get('text_i_am_returning_customer');
$data['text_forgotten'] = $this->language->get('text_forgotten');
$data['entry_email'] = $this->language->get('entry_email');
$data['entry_password'] = $this->language->get('entry_password');
$data['button_continue'] = $this->language->get('button_continue');
$data['button_login'] = $this->language->get('button_login');
if (isset($this->error['warning'])) {
$data['error_warning'] = $this->error['warning'];
} else {
$data['error_warning'] = '';
}
$data['action'] = $this->url->link('account/login', '', 'SSL');
$data['register'] = $this->url->link('account/register', '', 'SSL');
$data['forgotten'] = $this->url->link('account/forgotten', '', 'SSL');
if (isset($this->session->data['success'])) {
$data['success'] = $this->session->data['success'];
unset($this->session->data['success']);
} else {
$data['success'] = '';
}
if (isset($this->request->post['email'])) {
$data['email'] = $this->request->post['email'];
} else {
$data['email'] = '';
}
if (isset($this->request->post['password'])) {
$data['password'] = $this->request->post['password'];
} else {
$data['password'] = '';
}
} else {
$json['error'] = $this->language->get('error_login');
}
$this->response->addHeader('Content-Type: application/json');
$this->response->setOutput(json_encode($json));
}
protected function validate() {
$this->event->trigger('pre.customer.login');
// Check how many login attempts have been made.
$login_info = $this->model_account_customer->getLoginAttempts($this->request->post['email']);
if ($login_info && ($login_info['total'] >= $this->config->get('config_login_attempts')) && strtotime('-1 hour') < strtotime($login_info['date_modified'])) {
$this->error['warning'] = $this->language->get('error_attempts');
}
// Check if customer has been approved.
$customer_info = $this->model_account_customer->getCustomerByEmail($this->request->post['email']);
if ($customer_info && !$customer_info['approved']) {
$this->error['warning'] = $this->language->get('error_approved');
}
if (!$this->error) {
if (!$this->customer->login($this->request->post['email'], $this->request->post['password'])) {
$this->error['warning'] = $this->language->get('error_login');
$this->model_account_customer->addLoginAttempt($this->request->post['email']);
} else {
$this->model_account_customer->deleteLoginAttempts($this->request->post['email']);
$this->event->trigger('post.customer.login');
}
}
return !$this->error;
}
}
This will help you.
Download files and folders for above codes
Hope it also help you
If you just want the login page then here is the tricks, create index.php or index.html at root folder then paste the following code and change URL_WITH_SHOP in the code with your url with shop like "http://www.example.com/shop" :
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
<div class="container">
<div class="row">
<div id="content" class="col-sm-12 ">
<div class="row ">
<div class="col-sm-6" style="margin: 0px auto; float: none;">
<div class="well">
<h2>Returning Customer</h2>
<p><strong>I am a returning customer</strong></p>
<form action="URL_WITH_SHOP/index.php?route=account/login" method="post" enctype="multipart/form-data">
<div class="form-group">
<label class="control-label" for="input-email">E-Mail Address</label>
<input type="text" name="email" value="" placeholder="E-Mail Address" id="input-email" class="form-control" />
</div>
<div class="form-group">
<label class="control-label" for="input-password">Password</label>
<input type="password" name="password" value="" placeholder="Password" id="input-password" class="form-control" />
</div>
<input type="submit" value="Login" class="btn btn-primary" />
</form>
</div>
</div>
</div>
</div>
</div>
</div>
The issue will be if the customer enters wrong username and password then it redirects to the actual login page.