probably I'm doing something wrong, I have been coding by instinct haha. Laravel validation seems super easy to implement but for some reason between my vuejs component to my php function I'm always getting "required".
I'm new with both Laravel and Vuejs, it seems to me that my php function is fine (for what I can see on the web) but probably I'm missing something on the comunication between laravel and vue. Can you tell me whats wrong?
public function createTag(Request $request)
{
try {
$data = request()->validate([
'title' => 'required'
]);
$tag = new Tag;
$tag->title = $request->title;
if($tag->save())
{
$tag->usercontracts()->attach($request->usercontractId);
}
return response()->success(__('success.showing', ['resource' => 'des Vertrags', 'resourceE' => 'tag']), $tag->id, 200);
} catch (Exception $e) {
return response()->error(__('error.showing', ['resource' => 'des Vertrags', 'resourceE' => 'tag']), 400, $e);
}
}
<template>
<div id="relative">
<button #click.prevent="show = 1" v-if="show == 0">+tag</button>
<input type="text" v-model="title" name="title" v-if="show == 1">
<button #click="createTag" v-if="show == 1">add</button>
</div>
</template>
<script>
import TagService from "#/services/TagService";
export default {
name: "add-tag-component",
props: ['usercontractId'],
data(){
return {
title:null,
show:0
};
},
methods:
{
async createTag()
{
const {body: {data}} = await TagService.createTag(this.title, this.usercontractId);
this.$emit('addedTag', this.title, data);
this.title = '';
this.show = 0;
}
}
};
</script>
And this is TagService
export default {
createTag(title, usercontractId, tagId) {
return Vue.http.post(`contract/createTag/${title}/${usercontractId}`, tagId);
}
}
I'm also getting this error. May be here is the answer?
Vue warn]: Error in v-on handler (Promise/async): "[object Object]"
found in
---> at resources/assets/js/components/contract/listing/AddTagComponent.vue
at resources/assets/js/components/contract/listing/ContractListingItemComponent.vue
at resources/assets/js/components/contract/listing/ContractListingComponent.vue
In your TagService
You need to pass the ${title} as payload not as uri.
export default {
createTag(title, usercontractId, tagId) {
return Vue.http.post(`contract/createTag/${title}/${usercontractId}`, tagId);
}
}
to
export default {
createTag(title, usercontractId, tagId) {
return Vue.http.post(`contract/createTag`, {
tagId: tagId,
title: title,
usercontractId: usercontractId
});
}
}
Laravel validates the payload you pass.
Related
Am working on an app that should upload multiple images in the database using laravel and vue js.
Now for some reason it keeps on returning null value on the back end side. Hope someone can pin point the problem in this code.
this is my front-end code vue js
<template>
<div>
<div>
<form #submit.prevent="submit">
<input type="file" #change="onChange" multiple/>
<input type="submit" value="Upload">
</form>
</div>
</div>
</template>
<script>
export default {
data: ()=>({
image:[],
}),
methods:{
onChange(e){
this.image = e.target.files[0];
},
submit(){
let payload = new FormData();
for(let i=0; i<this.image.length; i++){
payload.append('image[]', this.image[i])
}
axios.post('/api/formsubmit',payload).then(res=>{
console.log("Response", res.data)
}).catch(err=>console.log(err))
}
},
}
</script>
and this is may back-end code Laravel 7
public function multipleupload(Request $request)
{
try{
if($request->hasFile('image')){
$upload = $request->file('image');
$file_name = time().'.'.$upload->getClientOriginalName();
$upload->move(public_path('image'), $file_name);
return response()->json([
'message'=>'File upload successfully!'
], 200);
}else {
return 'no data';
}
}catch(\Exception $e){
return response()->json([
'message'=>$e->getMessage()
]);
}
}
This code will always return 'no data'. been trying to figure it out but with no progress I hope someone can help.
Thanks,
if you want to upload multiple images you have to do loop, you can try this :
public function multipleupload(Request $request)
{
$input = $request->all();
request()->validate([
'image' => 'required',
]);
if($request->hasfile('image'))
{
foreach($request->file('image') as $image)
{
$imageName=file_name =$image->getClientOriginalName();
$image->move(public_path().'/images/', $imageName);
$insert['image'] = "$imageName";
}
}
Image::create($insert);
return back()
->with('success','Multiple Image Upload Successfully');
}
when I try to create a new subscription I get this error (This customer has no attached payment source or default payment method. ) so I checked the PaymentController with dd($paymentMethod) which returned null
so I don't know why the variable $paymentMethod in store method is returning NULL from the $request but the request, for the price is returning the price_id. Please any help is appreciated
but when console.log() setupIntent.payment_method it returned the payment_method in the console
Here is my PaymentController
public function index()
{
$availablePlans = [
'price_1HnIiLLzAo4pwMcyh2aGaznB' => 'Monthly',
'price_1HnJ2vLzAo4pwMcygQT66juk' => 'Yearly',
'price_1HnIhILzAo4pwMcy9iH3j30L' => 'Free Membership'
];
$user = auth()->user();
$data = [
'intent' => $user->createSetupIntent(),
'plans' => $availablePlans
];
return view('payments.checkout')->with($data);
}
public function store(Request $request)
{
$user = auth()->user();
$paymentMethod = $request->payment_method;
// dd($paymentMethod);
$planId = $request->plan;
$user->newSubscription('premium', $planId)->create($paymentMethod);
return response(['status' => 'success']);
}
This is the Javascript
window.addEventListener('load', function (){
// Create a Stripe client.
const stripe = Stripe('pk_test_51H2OqqLzAo4pwMcyT4h405wpFRAn3FWhvByfvmVnW6tabrIsDoU1dBXJ0UaWexUJeacCJ9uKpb5OBmmA2KaCg4sd00ZZ5tj2q8');
// Create an instance of Elements.
const elements = stripe.elements();
// Custom styling can be passed to options when creating an Element.
// (Note that this demo uses a wider set of styles than the guide below.)
// const cardElement = elements.create('card', {style: style});
// Create an instance of the card Element.
const cardElement = elements.create('card');
// Add an instance of the card Element into the `card-element` <div>.
cardElement.mount('#card-element');
const cardHolderName = document.getElementById('card-holder-name');
const cardButton = document.getElementById('card-button');
const clientSecret = cardButton.dataset.secret;
const plan = document.getElementById('subscription-plan').value;
cardButton.addEventListener('click', async (e) => {
const { setupIntent, error } = await stripe.handleCardSetup(
clientSecret, cardElement, {
payment_method_data: {
billing_details: { name: cardHolderName.value }
}
}
);
if (error) {
// Display "error.message" to the user...
} else {
// The card has been verified successfully...
// console.log('handling success', setupIntent.payment_method);
axios.post('/subscribe', {
payment_method: setupIntent.payment_method,
plan: plan
})
}
});
});
Here is the form
<form action="{{ route('subscribe')}}" method="POST" id="">
#csrf
<div class="form-content">
<div class="field">
<select class="form-control" name="plan" id="subscription-plan">
#foreach ($plans as $key=>$plan )
<option value="{{$key}}">{{$plan}}</option>
#endforeach
</select>
</div>
<div class="field">
<input type="text" autocorrect="off" spellcheck="false" id="card-holder-name" maxlength="25" />
<span class="focus-bar"></span>
<label for="cardholder">Card holder (Name on card)</label>
</div>
<div class="field mb-5" id="card-element">
<!-- Stripe Elements Placeholder -->
</div>
<button id="card-button" data-secret="{{ $intent->client_secret }}"><span>Pay</span></button>
</div>
</form>
The Route
Route::resource('payments', 'PaymentsController', [
'names'=> [
'index' => 'checkout',
'store' => 'subscribe',
]
]);
Looks like there is something wrong with how you're using axios. Have you tried taking a look at laravel simple axios with argument
Adding a hidden input field in the form and setting the value to setupIntent.payment_method passed the payment_method id to the controller which is used to create the subscription so the problem is solved.
A few modifications and adding a hidden input field to the JS
// Handle form submission.
var form = document.getElementById('payment-form');
form.addEventListener('submit', async (e) => {
e.preventDefault();
//cardButton.addEventListener('click', async (e) => {
//e.preventDefault()
const { setupIntent, error } = await stripe.handleCardSetup(
clientSecret, cardElement, {
payment_method_data: {
billing_details: { name: cardHolderName.value }
}
}
);
if (error) {
// Display "error.message" to the user...
} else {
// The card has been verified successfully...
//console.log('handling success', setupIntent.payment_method);
axios.post('/subscribe',{
plan : plan
})
var paymentMethod = setupIntent.payment_method;
var form = document.getElementById('payment-form');
var hiddenInput = document.createElement('input');
hiddenInput.setAttribute('type', 'hidden');
hiddenInput.setAttribute('name', 'payment_method');
hiddenInput.setAttribute('value', paymentMethod);
form.appendChild(hiddenInput);
// Submit the form
form.submit();
}
I am first using input in vue js . this input have structure like this
induk_id:'',
nama_barang:'',
qtt:'',
satuan:'',
harga:'',
harga_total:'',
keterangan:'',
status:'Aktif',
this induk_id is foreign key on another table , but i dont know how to pass this induk_id on this vue .
i use laravel vue js and this is controller and route
public function input_detail($id)
{
$pencairan = IndukPencairan::findOrFail($id);
if (!$pencairan)
abort(404);
return view('pengadaan.inputdetail',['pencairan' => $pencairan]);
}
this controller on laravel blade i can pass like $pencairan->id for this induk_id , but how i can pass this on vue ?
and its my route
Route::get('input_detail/{id}', 'PengadaanController#input_detail')->name('input_detail');
and its my export default
export default {
data(){
return{
count: 0,
userData:[{
induk_id:'',
nama_barang:'',
qtt:'',
satuan:'',
harga:'',
harga_total:'',
keterangan:'',
status:'Aktif',
}],
}
},
components:{
},
methods:{
submit() {
this.errors = {};
axios.post('/pengadaan/store_induk_pencairan', this.userData).then(response => {
window.location = response.data.redirect;
}).catch(error => {
if (error.response.status === 422) {
this.errors = error.response.data.errors || {};
}
});
},
AddField: function () {
this.userData.push({ induk_id: '',nama_barang: '' ,qtt: '' ,satuan: '',harga: '' ,harga_total: '',
keterangan: '' ,status: 'Aktif',
});
}
},
my question is how i retrieve induk_id in vue js ?
Your question is quite unclear, it needs a better explanation. Do you mean how to pass the 'induk_id' on axios post request. If that's the case, it's quite easy.
Call the submit function on vue passing the induk_id paramater whenever you want to action to be performed.
<button #click="submit(induk_id)"> Submit </button>
Then in methods, accept the parameter and concat using template literals ``
submit(id) {
this.errors = {};
axios.post(`/pengadaan/store_induk_pencairan/${id}`, this.userData).then(response => {
window.location = response.data.redirect;
}).catch(error => {
if (error.response.status === 422) {
this.errors = error.response.data.errors || {};
}
});
}
That's it, if its something you are looking for. But I'm not sure if you were asking about this, just my assumptions. Feel free to add more details.
<template>
<div>{{ response_data }}</div>
</template>
<script>
import axios from "axios";
export default {
data() {
return {
formdata: {
induk_id: "",
nama_barang: "",
qtt: "",
satuan: "",
harga: "",
harga_total: "",
keterangan: "",
status: "Aktif",
},
response_data: null,
};
},
methods: {
submit() {
axios
.get(`input_detail/${this.formdata.induk_id}`)
.then((response) => {
this.response_data = response.data;
})
.catch((error) => {
console.log(error);
});
},
},
};
</script>
<style lang="scss" scoped></style>
Im struggling to get a Laravel Cashier Strip integration to work with 3d secure cards.
I have go it setup so subscription works and is showing up in my stripe dashboard and everything it getting to my local database.
But when I test with cards that needs strong authntication as 3ds they get the status of incomplete in my stripe dashboard.
I get the cashier.payment response page in my console log. but isn't Cashier supposed to redirect to this confirmation window?
My code is as follows
In my subscription controller i have
public function index() {
$data = [
'intent' => auth()->user()->createSetupIntent(),
// 'plans' => $available_plans
];
return view('artists.subscription')->with($data);
}
public function checkout(Request $request) {
$user = auth()->user();
$paymentMethod = $request->payment_method;
$planId = 'monthly_sub';
// SCA
try {
$subscription = $user->newSubscription('monthly', $planId)->create($paymentMethod);
} catch (IncompletePayment $exception) {
return redirect()->route(
'cashier.payment',
[$exception->payment->id, 'redirect' => route('front')]
);
}
// return response(['status' => 'Success']);
}
and in my stripe js file I have this
const stripe = Stripe('stripe_key'); // i have my test key here
const elements = stripe.elements();
const cardElement = elements.create('card',{hidePostalCode: true});
cardElement.mount('#card-element');
const cardHolderName = document.getElementById('card-holder-name');
const cardButton = document.getElementById('card-button');
const clientSecret = cardButton.dataset.secret;
cardButton.addEventListener('click', async (e) => {
const { setupIntent, error } = await stripe.confirmCardSetup(
clientSecret, {
payment_method: {
card: cardElement,
billing_details: { name: cardHolderName.value }
}
}
);
axios.post('checkout', {
payment_method: setupIntent.payment_method
}).then(response => {
console.log(response.request.responseURL)
})
.catch(error => {
console.log(error.response)
});
});
My blade view is
#extends('layouts.app')
#section('head')
#php
// dd($intent);
#endphp
<script src="https://js.stripe.com/v3/"></script>
<link href="{{ asset('css/stripe.css') }}" rel="stylesheet">
#endsection
#section('content')
<input id="card-holder-name" type="text">
<!-- Stripe Elements Placeholder -->
<div id="card-element"></div>
<button id="card-button" data-secret="{{ $intent->client_secret }}">
subscribe
</button>
#endsection
#section('js')
<script src="{{ asset('js/stripe.js') }}" type="text/javascript"></script>
#endsection
Everything seems to be working but I just get the 3ds confirmation page as a response in my console. How do I get laravel to redirect and open that page for the user?
I think the issue is the order of events, your code should wait for 3DS to be called and completed before calling back to your code after the result is handed back to you. Using this regulator card [1] you should be able to test that with some small changes like this (I had to remove some things but this should be a reference):
stripe.confirmCardSetup(
"seti_xxx", {
payment_method: {
card: card,
billing_details: { name: "Name" }
}
}).then(function(result) {
// Check the result status here!!
axios.post('checkout', {
payment_method: result.setupIntent.payment_method
}).then(response => {
console.log(response.request.responseURL)
}).catch(error => {
console.log(error.response)
});
});
Hope this helps!
[1] https://stripe.com/docs/testing#regulatory-cards
I am trying to conditionally render element(s) based on a computed property but not having much luck even though my computed property is returning true or false correctly.
I am passing the user object in as a property (from Laravel) and all is working fine. I am able to see the user -- and their related role(s).
I've tested via Laravel to make sure I am sending the correct user and the relationship and everything looks good there as well.
Controller
$user = User::with('roles')->find(Auth::id());
blade
<my-component :user="{{ $user }}"></my-component>
VueComponent.vue
<template>
<div>
<div v-if="admin">
<p>You are an admin!</p>
</div>
<div v-else>
<p>You are not an admin.</p>
</div>
</div>
</template>
<script>
export default {
...
computed: {
admin: function () {
this.user.roles.forEach((role) => {
console.log('role: ', role); // role: admin (string)
if (role.name === 'admin') {
console.log('user is an admin!'); // I am getting here.
return true;
} else {
console.log('user is NOT an admin.');
}
});
return false;
},
},
methods: {
//
},
props: {
user: {
type: Object,
required: true,
},
},
}
</script>
I'm sure I am not implementing the computed property correctly; any help is greatly appreciated!
You problem is using foreach in wrong way! please use this instead:
computed: {
admin: function () {
for (var i = 0; i < this.user.roles.length; i++){
if ( this.user.roles[i].name === 'admin') {
return true;
}
}
return false;
}
}
you can read this article about forEach in js https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach
Your mistake was return true from forEach callback function and leave this true value useless and then return false value on admin function.