function is not called upon submit - javascript

I created this form to submit some info to the server-side. The form is in HTML/CSS and I am using AngularJS latest version. I also made sure that the button is inside the form. I know its most common mistake. But still, it's not working. The function I want to call is "onAddEditTenantSubmitForm" which is also assigned to state as well. I have checked it using the Chrome browser and marked line number 87. but it does not trigger. Also there is no error in the console too.
Below is the link to JSFiddle
https://jsfiddle.net/jLtsuonx/
'''
(function () {
var app = angular.module('app');
app.controller('MultiTenantController', ['$scope', '$filter', 'TenantServices', function ($scope, $filter, TenantServices) {
var uibModal = null;
var test = "Multi Tenat Controller";
var state = {
tenantModel: {
addedOn: '',
connectionString: '',
createdBy: '',
endOn: '',
id: '',
identifier: '',
isDisabled: '',
items: [{
isDisabled: '',
tenantType: '',
}],
name: '',
startFrom: '',
tenantType: '',
userId: '',
},
};
var init = function () {
$(document).ready(function () {
tenantTable = $('#table_Tenants').DataTable({
ajax: {
url: 'API/MultiTenant/Pagged',
method: 'POST'
},
columns: [
{ data: 'name' },
{ data: 'identifier' },
{ data: 'connectionString' },
{
data: 'startFrom',
render: function (startFrom) {
return $filter('date')(startFrom, 'medium');
}
},
{
data: 'addedOn',
render: function (addedOn) {
return $filter('date')(addedOn, 'medium');
}
},
{
data: 'endOn',
render: function (endOn) {
return $filter('date')(endOn, 'medium');
}
},
{
data: 'actions',
orderable: false,
render: function () {
return `<div class="list-icons">
<div class="dropdown">
<a href="#" class="list-icons-item" data-toggle="dropdown">
<i class="icon-menu9"></i>
</a>
<div class="dropdown-menu dropdown-menu-right">
<i class="icon-database-edit2"></i>Edit
<i class="icon-database-remove"></i>Delete
</div>
</div>
</div>`;
}
}
]
});
tenantTable.on('click', '.deleteTenant', function () {
const $row = $(this).closest('tr');
const rowData = tenantTable.row($row).data();
deleteTenant(rowData);
});
})
};
const onAddEditTenantSubmitForm = function (newTenatForm) {
if (!state.tenantModel.userId) {
addTenant(newTenatForm);
}
else {
//updateUser(newUserForm);
}
};
var addTenant = function (newTenatForm) {
state.isLoading = true;
TenantServices.addTenant(state.tenantModel).then(
function () {
swalInit.fire({
title: 'Success',
text: 'Tenant has been created',
type: 'success'
});
userTable.ajax.reload();
closeModal();
},
function (errorResponse) {
if (errorResponse.status === 400 && errorResponse.data.duplicateRecord) {
}
else if (errorResponse.status === 500) {
swalInit.fire({
title: 'Server Error',
text: 'An server error occurred while adding tenant.',
type: 'error'
});
}
}
)
.finally(() => state.isLoading = false);
};
var deleteTenant = function (rowObj) {
state.isLoading = true;
TenantServices.deleteTenant(rowObj.id).then(
function () {
swalInit.fire({
title: 'Success',
text: 'Tenant Deleted!',
type: 'success'
});
tenantTable.ajax.reload();
closeModal();
},
function (errorResponse) {
if (errorResponse.status === 500) {
swalInit.fire({
title: 'Server Error',
text: 'An server error occurred while Deleting Tenant.',
type: 'error'
});
}
else if (errorResponse.status === 404) {
swalInit.fire({
title: 'Server Error',
text: 'Tenant not found on Server.',
type: 'error'
});
}
}
)
.finally(() => state.isLoading = false);
};
var closeModal = function () {
if (uibModal) {
uibModal.close();
}
};
state.onAddEditTenantSubmitForm = onAddEditTenantSubmitForm;
state.test = test;
$scope.state = state;
$scope.init = init;
}]);
})();
'''

You need the function you are calling on the template via ng-submit to be in your scope and then change the template to call it correctly.
On your controller update your function from a const and tie it to scope
$scope.onAddEditTenantSubmitForm = function (newTenatForm) {
On your template add "$ctrl." as a prefix to your function
ng-submit="$ctrl.onAddEditTenantSubmitForm(newTenatForm)"

Related

In Vue v2, How do I verify if a value entered into a form is empty?

I've tried many different ways to do this with both alert() and simple if-else statements, and even what is at this link: https://v2.vuejs.org/v2/cookbook/form-validation.html
But nothing works! What am I doing wrong?
What is in my index.html:
<div id="app">
<div class = "addTask">
<h1>A List of Tasks</h1>
<p v-show="activeItems.length === 0">You are done with all your tasks! Celebrate!</p>
<form #submit.prevent="addItem">
<input type="text" v-model="title">
<button type="submit">+</button>
</form>
</div>
This is what I have in scripts.js:
var app = new Vue({
el: '#app',
data () {
return {
// errors: [],
items: [{
userId: 0,
id: 0,
title: "",
completed: false,
}],
title: '',
show: 'all',
}
},
// Using axios to asynchrously query the API
mounted () {
axios
.get("https://jsonplaceholder.typicode.com/todos")
.then(response => this.items = response.data)
},
computed: {
activeItems() {
this.saveItems;
return this.items.filter(item => {
return !item.completed;
});
},
filteredItems() {
// An active state denotes the task is not yet completed
if (this.show === 'active')
return this.items.filter(item => {
return !item.completed;
});
if (this.show === 'completed')
return this.items.filter(item => {
return item.completed;
});
// This makes it so added tasks go to the top, not bottom
return this.items.reverse();
},
},
methods: {
addItem() {
if(this.items != 0) {
this.items.push({
title: this.title,
completed: false
})
this.title = "";
}
else {
alert("Please enter a task.")
}
Based on your code, you should declare a property called title in the data function and check if title is empty or not in addItem method.
var app = new Vue({
el: '#app',
data () {
return {
// errors: [],
title: '', // add this property in data function
items: [{
userId: 0,
id: 0,
title: "",
completed: false,
}],
title: '',
show: 'all',
}
},
// Using axios to asynchrously query the API
mounted () {
axios
.get("https://jsonplaceholder.typicode.com/todos")
.then(response => this.items = response.data)
},
computed: {
activeItems() {
this.saveItems;
return this.items.filter(item => {
return !item.completed;
});
},
filteredItems() {
// An active state denotes the task is not yet completed
if (this.show === 'active')
return this.items.filter(item => {
return !item.completed;
});
if (this.show === 'completed')
return this.items.filter(item => {
return item.completed;
});
// This makes it so added tasks go to the top, not bottom
return this.items.reverse();
},
},
methods: {
addItem() {
if(this.title !== '') { //check if `title` is empty or not
this.items.push({
title: this.title,
completed: false
})
this.title = "";
}
else {
alert("Please enter a task.")
}
I created an example in Stackblitz. You can also view the example directly by clicking here

Access the outer items of an object in a function of that object

I've used Dock of PrimeReact.
<Dock model={options.buttons} position="right"/>
According to its document, For model we should pass its dockItems.
So I defined options like this:
I have an array of objects. Inside it I have buttons, I want to check if the xValue doesn't have value then I show an error message.
const options = [
{
xValue: '',
uperMessage: 'Select a start date',
lowerMessage: '',
setMessage: function (time) {
this.lowerMessage = `Selected start date: ${dateHelper.formatDate(time)}`;
},
buttons: [
{
label: 'Next',
icon: () => <Button label="Next" className="p-button-success" />,
command: function () {
if (!this.xValue) {
toast.current.show({ severity: 'error', summary: 'Error', detail: 'Select a start date!', life: 3000 });
} else {
setCurrentStep(2);
}
}
},
{
label: 'Cancel',
icon: () => <Button label="Cancel" className="p-button-secondary" />,
command: () => {
cancel()
}
}
]
},
{
xValue: '',
uperMessage: 'Select a end date',
lowerMessage: '',
setMessage: function (time) {
this.lowerMessage = `Selected end date: ${dateHelper.formatDate(time)}`;
},
buttons: [
{
label: 'Next',
icon: () => <Button label="Next" className="p-button-success" />,
command: function (xValue) {
if (!this.xValue) {
toast.current.show({ severity: 'error', summary: 'Error', detail: 'Select a Divergence end date!', life: 3000 });
} else {
setCurrentStep(3);
}
}
},
{
label: 'Cancel',
icon: () => <Button label="Cancel" className="p-button-secondary" />,
command: () => {
cancel()
}
}]
}];
How can I access the xValue in the command function?
If I use this, it gets the items of the current scope. How can I access the items of the parent?
Any help would be greatly appreciated.
You can change command function and map on the options items, also buttons items. Finally you can find the current item and get the xValue :
command: function () {
let $this = this;
options.map((option,oindex)=>{
option.buttons.map(button,binex)=>{
if(button == $this)
if (!option.xValue) {
toast.current.show({ severity: 'error', summary: 'Error', detail: 'Select a start date!', life: 3000 });
} else {
setCurrentStep(2);
}
})
})
you could use the array name "options" to access xValue like that
if(!options[item_index]['xValue']){
....
}
for example:- options[0]["xValue"] => // return ''

Hosted fields in braintree gives error "Cannot determine payment method" PHP Laravel

Can anyone please explain me how could i make a working Braintree payment with hosted fields, in Laravel. I tried to look at the documentation myself but i couldn't make it working.
i created the token in the controller to be sent to the view like:
$gateway = new \Braintree\Gateway([
'environment' => config('services.braintree.environment'),
'merchantId' => config('services.braintree.merchantId'),
'publicKey' => config('services.braintree.publicKey'),
'privateKey' => config('services.braintree.privateKey')
]);
$paypalToken = $gateway->ClientToken()->generate();
return view('checkout')->with(['paypalToken' => $paypalToken]);
On the blade view i have this JS:
var form = document.querySelector('#payment-form');
var submit = document.querySelector('input[type="submit"]');
braintree.client.create({
authorization: '{{ $paypalToken }}'
}, function (clientErr, clientInstance) {
if (clientErr) {
console.error(clientErr);
return;
}
braintree.hostedFields.create({
client: clientInstance,
styles: {
'input': {
'font-size': '14px'
},
'input.invalid': {
'color': 'red'
},
'input.valid': {
'color': 'green'
}
},
fields: {
number: {
selector: '#card-number',
placeholder: '4111 1111 1111 1111'
},
cvv: {
selector: '#cvv',
placeholder: '123'
},
expirationDate: {
selector: '#expiration-date',
placeholder: '10/2019'
}
}
}, function (hostedFieldsErr, hostedFieldsInstance) {
if (hostedFieldsErr) {
console.error(hostedFieldsErr);
return;
}
// submit.removeAttribute('disabled');
form.addEventListener('submit', function (event) {
event.preventDefault();
hostedFieldsInstance.tokenize(function (tokenizeErr, payload){
if (tokenizeErr) {
console.error(tokenizeErr);
return;
}
document.querySelector('#nonce').value = payload.nonce;
form.submit();
});
}, false);
});
// Create a PayPal Checkout component.
braintree.paypalCheckout.create({
client: clientInstance
}, function (paypalCheckoutErr, paypalCheckoutInstance) {
if (paypalCheckoutErr) {
console.error('Error creating PayPal Checkout:', paypalCheckoutErr);
return;
}
// Set up PayPal with the checkout.js library
paypal.Button.render({
env: 'sandbox', // or 'production'
commit: true,
payment: function () {
return paypalCheckoutInstance.createPayment({
flow: 'checkout', // Required
amount: '{{ presentPrice($newTotal + 5000) }}', // Required
currency: 'USD', // Required
});
},
onAuthorize: function (data, actions) {
return paypalCheckoutInstance.tokenizePayment(data, function (err, payload) {
// Submit `payload.nonce` to your server.
document.querySelector('#nonce').value = payload.nonce;
form.submit();
});
},
onCancel: function (data) {
console.log('checkout.js payment cancelled', JSON.stringify(data, 0, 2));
},
onError: function (err) {
console.error('checkout.js error', err);
}
}, '#paypal-button').then(function () {
// The PayPal button will be rendered in an html element with the id
// `paypal-button`. This function will be called when the PayPal button
// is set up and ready to be used.
});
});
});
Here is the method in were i process the payment:
$gateway = new \Braintree\Gateway([
'environment' => config('services.braintree.environment'),
'merchantId' => config('services.braintree.merchantId'),
'publicKey' => config('services.braintree.publicKey'),
'privateKey' => config('services.braintree.privateKey')
]);
$nonce = $request->payment_method_nonce;
$result = $gateway->transaction()->sale([
'amount' => round(getNumbers()->get('newTotal') / 100, 2),
'paymentMethodNonce' => $nonce,
'options' => [
'submitForSettlement' => True
]
]);
if ($result->success) {
$transaction = $result->transaction;
$order = $this->addToOrdersTablesPaypal(
$email,
$firstName.' '.$lastName,
null
);
return redirect()->route('confirmation.index')->with('success_message', 'Thank you! Your payment has been successfully accepted!');
} else {
$order = $this->addToOrdersTablesPaypal(
$email,
$firstName.' '.$firstName,
$result->message
);
return back()->withErrors('An error occurred with the message: '.$result->message);
}
can anyone help me, understand what is missing?
i solved it, i actually found an workaround, i had to create a controller for the hosted fields, and it worked.

[Vue warn]: Error in v-on handler: "TypeError: Cannot read property 'id' of undefined" in VueJS and Laravel

I have a table with the ability to add new items and edit existing ones (with the edit button being next to each entry). I have an issue with it whereby if you were to add a new item, NOT refresh the page, but then go to edit the item, it will edit it on Vue but not pass the edit back to the database. When you go to edit an item, the PUT URL returns a 404 error. If however, you refresh the page after adding an item, you can edit it perfectly fine. Any ideas what I've done wrong, or maybe forgotten to add? Same for the delete method too.
<script>
export default {
data: () => ({
dialog: false,
headers: [
{
text: 'Question',
align: 'left',
sortable: true,
value: 'question',
width: '25%'
},
{ text: 'Answer', value: 'answer', width: '55%' },
{ text: 'Actions', value: 'action', sortable: false, width: '20%' },
],
questions: [],
editedIndex: -1,
editedItem: {
question: '',
answer: ''
},
defaultItem: {
question: '',
answer: ''
},
}),
computed: {
formTitle () {
return this.editedIndex === -1 ? 'New Item' : 'Edit Item'
},
},
watch: {
dialog (val) {
val || this.close()
},
},
created () {
this.initialize();
this.loadUsers();
},
methods: {
initialize () {
this.questions = []
},
loadUsers(){
if (axios == null) {
return;
}
axios.get('/api/faq').then(res=>{
if(res.status === 200){
this.questions=res.data;
}
}).catch(err=>{
console.log(err);
});
},
editItem (item) {
this.editedIndex = this.questions.indexOf(item);
this.editedItem = Object.assign({}, item);
this.dialog = true
},
deleteItem (item) {
const index = this.questions.indexOf(item);
confirm('Are you sure you want to delete this item?') &&
axios.destroy('/api/faq/' + this.questions[this.editedIndex].id).then(response =>{
this.questions.splice(index, 1);
}).catch(error=>{
console.log('Deleting error')
})
},
close () {
this.dialog = false;
setTimeout(() => {
this.editedItem = Object.assign({}, this.defaultItem);
this.editedIndex = -1
}, 300)
},
saveToServer () {
if (this.editedIndex > -1) {
// Edit item
Object.assign(this.questions[this.editedIndex], this.editedItem);
axios.put('/api/faq/' + this.questions[this.editedIndex].id, this.editedItem).then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
} else {
//New item
this.questions.push(this.editedItem);
axios.post('/api/faq', this.editedItem).then(function (response) {
console.log('Before');
this.id = response.id;
console.log('After');
Object.assign(this.questions[this.editedIndex], this);
console.log(response);
})
.catch(function (error) {
console.log(error);
});
}
this.close()
},
},
}
</script>
Store Controller:
public function store(Request $request)
{
$id = faq::insertGetId($request->all());
return Response:: json([
'status' => 'ok',
'id' => $id,
], 200);
}
Update Controller:
public function update(Request $request, $id)
{
faq::findOrFail($id)->update($request->all());
return response(['message' => 'Success']);
}

How to do a synchronous call with jaydata

I'm a bit confused about the asynchous call to the DataBase.
I just want to have a javasctipt adapter class for the calls to the web sql. But I'm not quite sure how to do this. Propably somebody have a good hint for me.
The function OfflneAppDBAdapter.prototype.IsDeviceConfigured() should return true or false depending if there are any items in the Table DeviceConfig.
function OfflneAppDBAdapter() {
self = this;
this.deviceIsConfigured = false;
this.Init = function () {
$data.Entity.extend("$de.offlineapp.DeviceConfig", {
Id: { type: "int", key: true, computed: true },
Name: { type: "string", required: true },
Token: { type: "string" },
Type: { type: "string" }
});
$data.EntityContext.extend("$de.offlineapp.DataContext", {
DeviceConfig: { type: $data.EntitySet, elementType: $de.offlineapp.DeviceConfig }
});
}
self.Init();
$de.offlineapp.context = new $de.offlineapp.DataContext({
name: "webSql", databaseName: "OfflineApp"
});
$de.offlineapp.context.onReady(function () {
});
}
// ************************************************************************
// PUBLIC METHODS -- ANYONE MAY READ/WRITE
// ************************************************************************
OfflneAppDBAdapter.prototype.AddDeviceConfig = function (deviceName, deviceToken, deviceTyp) {
$de.offlineapp.context.onReady(function () {
var promise = $de.offlineapp.context.DeviceConfig.toArray(function (x) {
if (x.length == 0) {
var emp = new $de.offlineapp.DeviceConfig({ Name: deviceName, Token: deviceToken, Type: deviceTyp });
$de.offlineapp.context.DeviceConfig.add(emp);
$de.offlineapp.context.saveChanges();
}
}
)
});
}
OfflneAppDBAdapter.prototype.IsDeviceConfigured = function () {
$de.offlineapp.context.onReady(function () {
var promise = $de.offlineapp.context.DeviceConfig.toArray(function (x) {
if (x.length == 0) {
this.deviceIsConfigured = true;
}
}
)
});
return this.deviceIsConfigured;
}
var myOfflineAppDBAdapter = new OfflneAppDBAdapter();
myOfflineAppDBAdapter.AddDeviceConfig("DeviceName", "Token", "iPad");
console.log(myOfflineAppDBAdapter.IsDeviceConfigured());
As expected the console prints "false". I' aware that the jaydata call works with callbacks and the callbacks are not part of the main class. But there must be a possibility to do so?
I would really apprechiate any help.
Thank you in advance....
Chris
UPDATE:
As you requested the startup code:
function OfflineApplication()
{
self = this;
}
OfflineApplication.prototype.StartApplication = function () {
//Check if online, then sync and
if (navigator && navigator.onLine === true) {
this.IsDeviceConfigured();
}
else {
}
}
///check if the device has a base configuration
OfflineApplication.prototype.IsDeviceConfigured = function () {
myOfflineAppDBAdapter.GetDeviceConfiguration(function (result) {
if (result.length > 0) {
myOfflineAppDBAdapter.deviceIsConfigured = true;
myOfflineApplication.HasDeviceAnApplication();
}
else {
///Get the device base conf from the server.
myOfflineAppSynchronisationAdapter.getDeviceConfigurationByToken(token, myOfflineApplication.HasDeviceAnApplication);
myOfflineAppDBAdapter.deviceIsConfigured = true;
}
});
}
///check if the device has an "application config" in general
OfflineApplication.prototype.HasDeviceAnApplication = function () {
myOfflineAppDBAdapter.GetDeviceAnApplication(function (result) {
if (result.length > 0) {
myOfflineApplication.IsDeviceApplicationVersionLatest(result);
}
else {
myOfflineApplication.GetApplication(false);
}
});
}
///the application config could differ from time to time, so we have to check if a different application should be synct with the device
OfflineApplication.prototype.IsDeviceApplicationVersionLatest = function (result) {
myOfflineAppDBAdapter.DeleteDeviceAnApplication(function () { });
console.log(result);
}
///get the application from the server
OfflineApplication.prototype.GetApplication = function (clearConfig) {
if (clearConfig === true)
{
}
myOfflineAppSynchronisationAdapter.getDeviceApplicationByToken(token, myOfflineApplication.LoadApplication);
}
OfflineApplication.prototype.LoadApplication = function () {
console.log('Now everything is finde and the application gets loaded..');
}
var myOfflineAppDBAdapter = new OfflneAppDBAdapter();
var myOfflineAppSynchronisationAdapter = new OfflineAppSynchronisationAdapter();
var myOfflineApplication = new OfflineApplication();
myOfflineApplication.StartApplication();
There is no sync way. You handling promises wrong. Make your code simple :) You'll need something like this:
$data.Entity.extend("$de.offlineapp.DeviceConfig", {
Id: { type: "int", key: true, computed: true },
Name: { type: "string", required: true },
Token: { type: "string" },
Type: { type: "string" }
});
$data.EntityContext.extend("$de.offlineapp.DataContext", {
DeviceConfig: { type: $data.EntitySet, elementType: $de.offlineapp.DeviceConfig }
});
var context = new $de.offlineapp.DataContext({
name: "webSql", databaseName: "OfflineApp"
});
function AddDeviceConfig(deviceName, deviceToken, deviceTyp) {
return context.DeviceConfig.toArray()
.then(function (x) {
if (x.length == 0) {
var emp = new $de.offlineapp.DeviceConfig({ Name: deviceName, Token: deviceToken, Type: deviceTyp });
context.DeviceConfig.add(emp);
return context.saveChanges();
}
})
}
function IsDeviceConfigured() {
return context.DeviceConfig.toArray()
.then(function (x) {
return x.length > 0;
})
}
context.onReady()
.then(IsDeviceConfigured)
.then(console.log)
.then(function() { return AddDeviceConfig("DeviceName", "Token", "iPad"); })
.then(IsDeviceConfigured)
.then(console.log);
here's a fiddle which does this: http://jsfiddle.net/JayData/cpT5q/1/

Categories