.isDirty is true after submitting and reloading InertiaJS page - laravel

I have a simple form with a "Save" button that shows up if the user has updated any of the checkboxes.
The form sends a POST request to a store route in a controller that creates new records in the databases and redirects them to the index route.
When the page reloads, it doesn't seem to reset the Inertia form isDirty state from true to false even when I manually refresh the page.
public function index(Request $request)
{
$restaurantCategories = auth()->user()
->currentTeam->categories()
->with('category')->get();
$allCategories = Category::all();
$filters = $request->only('search');
return Inertia::render('Restaurant/Categories/Index',
[
'restaurantCategories' => $restaurantCategories,
'allCategories' => $allCategories, 'filters' => $filters
]);
}
public function store(Request $request)
{
foreach (auth()->user()->currentTeam->categories as $category) {
$category->delete();
}
foreach ($request->checkedCategories as $category) {
auth()->user()->currentTeam->categories()
->create(['category_id' => $category['id']]);
}
return redirect()->route('restaurant.categories.index');
}
Vue
export default{
props: {
filters: Object,
restaurantCategories: Object,
allCategories: Object,
},
data: {
updateForm: this.$inertia.form({
checkedCategories: this.restaurantCategories.map(
(resCat) => resCat.category
),
}),
}
}
methods:{
//THIS METHOD IS CALLED WHEN THE SAVE BUTTON IS CLICKED
sendUpdate() {
this.$inertia.post(
this.route("restaurant.categories.store"),
this.updateForm
);
},
},
}
I've tried setting a key to the save button and updating the key on sendUpdate method, and calling Inertia.reload()

Related

laravel using jQuery Ajax | Ajax Cart

I'm Trying to Save The Product into The Database By Clicking On Add To Cart
But It's Not Adding I Also Use Ajax `
I Want To Add The Cart To DataBase And It's Not Adding.
This is The Error That I cant Add Any Product To The Cart Because Of It
message: "Call to undefined method App\User\Cart::where()", exception: "Error",…
enter image description here
Model Page.
class Cart extends Model
{
use HasFactory; I
protected $table = 'carts';
protected $fillable = [
'user_id',
'prod_id',
'prod_qty',
];
}
Controller page.
public function addToCart(Request $request)
{
$product_qty = $request->input('product_qty');
$product_id = $request->input ('product_id');
if(Auth::check())
{
$prod_check = Product::where('id',$product_id)->first();
if($prod_check)
{
if(Cart::where('prod_id',$product_id)->where('user_id',Auth::id())->exists())
{
return response()->json(['status' => $prod_check->pname." Already Added to cart"]);
}
else
{
$cartItem - new Cart();
$cartItem->user_id = Auth::id();
$cartItem->prod_qty = $product_qty;
$cartItem->save();
return response()->json(['status' => $prod_check->pname." Added to cart"]);
}
}
}
else{
return response()->json(['status' => "Login to Continue"]);
}
}
javascript page.
This Is MY First Time To Use Ajax And Sure That Every Thing Is Correct I Want Know Why Its Not Add
$('.addToCartBtn').click(function (e) {
e.preventDefault();
var product_id = $(this).closest('.product_data').find('.prod_id').val();
var product_qty = $(this).closest('.product_data').find('.qty-input').val();
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
});
$.ajax({
method: "POST",
url: "/add-to-cart",
data: {
'product_id': product_id,
'product_qty': product_qty,
},
success: function (response) {
alert(response.status);
}
});
// alert(product_id);
// alert(product_qty);
// // alert ("test ") ;
});
Route:
Route::middleware(['auth'])->group(function () {
Route::post('/add-to-cart', [App\Http\Controllers\User\indexController::class, 'addToCart' ]);});
So why this error occurs, how can I fix it?`
This look like an error in importation like App\Models\Cart not like this?
verify if you had added use App\Models\Cart;

Axios gives undefined while accessing data at Vue's componenet in Laravel

I'm using Laravel and Vue's component, and when i try to access the banners property from response returned by axios in vue component it gives me undefined.
I am accessing the perperty like response.data.banners
I'm returning data from controller in following way:
public function getBanners(Request $request){
return response()->json(['
banners'=> BannerImage::active()->get()
]);
}
Here is how i am accessing axios response
<script>
export default {
data: function() {
return {
banners: []
}
},
mounted() {
axios.get("getBanners").then((res)=> {
console.log(res);
console.log(res.data);
console.log(res.data.banners);
this.banners = res.data.banners;
});
console.log('Component mounted.')
}
}
</script>
Response by axios
All is working before accessing the banners property. Is there anything i am not doing correct ?
You have an linebreak ↩ between ' and banners, which is shown in the console line 2 "↩ banners":
Problem
public function getBanners(Request $request){
return response()->json([' // <-- ↩ line break
banners'=> BannerImage::active()->get()
]);
}
Correct
public function getBanners(Request $request) {
return response()->json([
'banners' => BannerImage::active()->get()
]);
}

Redirect in inertia js and jetstream in javascript code

I want to be redirected to single question page after creation of question
summitQuestion(){
this.question_button = true
axios.post('/api/question/ask', {
'title' : this.question.title,
'body' : this.question.body,
'tags' : this.tags,
'user_id' : this.$page.props.user.id
}).then(response=>{
this.question_button = false
console.log(response.data)
}).catch(error=>{
this.question_button = false
console.log(error.response.data.errors)
if(error.response.data.errors){
this.title_errors = error.response.data.errors.title
this.body_errors = error.response.data.errors.body
}
})
},
I have this function I want after the success of the request to redirect I a spa way without page reloading to question single page I am using inertia js and jetstream my laravel router is below
Route::middleware(['auth:sanctum', 'verified'])->get('/question/{question}', 'App\Http\Controllers\QuestionController#show')->name('question-single');
Simply use the visit method on the inertia like shown below.
this.$inertia.visit(route('question-single'), { method: 'get' });
If you got everything correct from your code above remaining the redirection without your page reloading, then I guess the modification of your code will be the sample as folows;
summitQuestion(){
this.question_button = true
axios.post('/api/question/ask', {
'title' : this.question.title,
'body' : this.question.body,
'tags' : this.tags,
'user_id' : this.$page.props.user.id
}).then(response=>{
this.question_button = false
// console.log(response.data)
this.$inertia.visit(route('question-single'), { method: 'get', data: response.data });
}).catch(error=>{
this.question_button = false
console.log(error.response.data.errors)
if(error.response.data.errors){
this.title_errors = error.response.data.errors.title
this.body_errors = error.response.data.errors.body
}
})
},
You can make reference to this by visiting The Official Inertiajs Website
If you are using Inertia, you are supposed to create a form with v-model linked to fields. Add to that a button of type submit that call your method (see below the method example).
<form #submit.prevent="submitQuestion">
<input type="text" v-model="form.title">
<button type="submit"></button>
</form>
<script>
export default {
data() {
return {
form: this.$inertia.form({
title: this.question.title,
body: this.question.body,
tags: this.tags,
user_id: this.$page.props.user.id,
}, {
bag: 'default',
}),
}
},
methods: {
summitQuestion: function() {
this.form.post('/api/question/ask');
},
}
};
</script>
The redirection can be done directly on your controller method.
class QuestionController extends Controller
{
public function create(Request $request) {
// Create your question
return redirect()->route('your.route');
}
}

How to return back to a paginated page?

Using Laraver Inertia Vue
I use a vue with a paginated list of posts. For each post I only load a few column from the database such as title and author. Then I visit url to load the details of a chosen post in the list. I do so using visit url with the lazy loading functionality. After that I am ready to edit the post without reloading the full page. Once the post is updated I submit it and correctly save it into the database. After that I can return back to the page. Everything happens without any reloading on the list.
In order to be able to load the details on a specific post lazily, my on controller is like this.
class PostController extends Controller
{
public function Index($id = null)
{
$this->id = $id;
return Inertia::render('Posts/Index', [
'posts' => Post::select('id', 'title', 'created_at')
->addSelect([
'userfirstname' => User::select('firstname')->whereColumn('id', 'posts.user_id'),
'userlastname' => User::select('familyname')->whereColumn('id', 'posts.user_id')
])
->orderBy('created_at', 'DESC')
->paginate(10),
//lazily evaluated
'details' => function () {
if ($this->id) {
$post = Post::find($this->id);
} else {
$post = null;
}
return $post;
},
]);
}
public function Update(Request $request)
{
$request->validate([
'id'=>'required',
'abstract'=>'required',
//TODO :to be completed
]);
$post=Post::find($request->input('id'));
$post->abstract=$request->input('abstract');
$post->title=$request->input('title');
//TODO to be completed
$post->save();
return Redirect::back();
}
}
and the method I use to load page and details are these:
//visit this url to get the lazzy evaluation of post details
if (to_visit) {
this.$inertia
.visit(`/posts/${to_visit}`, {
method: "get",
data: {},
replace: false,
preserveState: true,
preserveScroll: true,
only: ["details"],
headers: {}
})
.then(to_visit => {
console.log("fetched " + this.details.title);
});
}
},
updatePost(form) {
console.log("form submitted");
this.$inertia.visit(`/post`, {
method: "put",
data: form,
replace: false,
preserveState: true,
preserveScroll: true,
only: [],
headers: {}
});
},
This works fine as long as the particular post I update is on the first page, but when it is on the any other paginated page on the list, post saving is ok but I don't return on the paginated page but always on the first one.
Would be happy to ear about a solution!

Yii2: ajax form validation on an ajax submitted form

I'm wondering if any Yii2 experts can help me understand how best to work with ajax forms combined with Yii ajax validation. I think I can explain the issue without taking you through all of my code.
I am working on a Promo Code entry form where the user enters their promo code into the form, the form is submit via ajax. We then perform a database lookup for the promo code details, validate the code and if the code validates, we want to display the registration form that is hidden on the page.
I have a custom validation function for the form field "code", which is the active field in a model scenario named "register".
class UserCode extends ActiveRecord
{
...
public function scenarios()
{
return [
'register' => ['code'],
];
}
public function rules()
{
return [
[['code'], 'required'],
[['code'], 'validateUserCode', 'on' => ['register']],
];
}
public function validateUserCode($attribute, $params)
{
// perform all my custom logic to determine if the code is valid
if ($code_invalid) {
$this->addError($attribute, 'Sorry, this code is invalid.');
}
}
...
}
Then in the controller, as the Yii2 Guide suggests, I trap this ajax validation with the following code:
public function actionValidate() {
$model = new UserCode(['scenario' => 'register']);
if (Yii::$app->request->isAjax && $model->load(Yii::$app->request->post())) {
Yii::$app->response->format = Response::FORMAT_JSON;
return ActiveForm::validate($model);
}
// no logic can be run after the above code b/c the form is submit with ajax
// and therefore always trapped in the Yii::$app->request->isAjax conditional
}
The above code all works fine and if I remove focus from the $form->field($model, 'code') field on my form, Yii's ajax validation kicks in and displays my custom error message based off of my custom validation logic.
My challenge arises when I go to submit the form. The form submission is also handled through ajax, and therefore the controller action always returns the result of the ActiveForm::validate($model); because if (Yii::$app->request->isAjax && $model->load(Yii::$app->request->post())) will get apply to both the ajax form validation AND on the form submit.
With the above approach, I am forced to return only the results of the ajax validation and not any json data that I may need for additional client side validation, such as displaying the registration form after a valid use code is submitted through the ajax form.
I realize that I can set 'enableAjaxValidation' => false on the ActiveForm and then return my own json data inside the if (Yii::$app->request->isAjax && $model->load(Yii::$app->request->post())) condition. If I do this, I am able to show the registration form because I have my own json data to work with.
Is there a way to have ajax validation on a form that is submitted with ajax? How could you trap the ajax validation separately from the ajax form submission to handle the two events in different manners?
Any suggestions or alternate approaches are GREATLY appreciated!
You should set up validationUrl with a different URL compared to the URL that you are submitting the form to. In this way you can have the validation function that would validate and return the return ActiveForm::validate($model); and the normal submit form that does something else.
You can read more about validationUrl here:
I have found solution :
Form :
<?php
$form = ActiveForm::begin(['id' => 'form-add-contact', 'enableAjaxValidation' => true, 'validationUrl' => Yii::$app->urlManager->createUrl('contacts/contacts/contact-validate')]);
?>
Submit Via Ajax :
<?php
$script = <<< JS
$(document).ready(function () {
$("#form-add-contact").on('beforeSubmit', function (event) {
event.preventDefault();
var form_data = new FormData($('#form-add-contact')[0]);
$.ajax({
url: $("#form-add-contact").attr('action'),
dataType: 'JSON',
cache: false,
contentType: false,
processData: false,
data: form_data, //$(this).serialize(),
type: 'post',
beforeSend: function() {
},
success: function(response){
toastr.success("",response.message);
},
complete: function() {
},
error: function (data) {
toastr.warning("","There may a error on uploading. Try again later");
}
});
return false;
});
});
JS;
$this->registerJs($script);
?>
Controller :
/*
* CREATE CONTACT FORM AJAX VALIDATION ACTION
*/
public function actionContactValidate() {
$model = new ContactsManagement();
if (Yii::$app->request->isAjax && $model->load(Yii::$app->request->post())) {
$model->company_id = Yii::$app->user->identity->company_id;
$model->created_at = time();
\Yii::$app->response->format = Response::FORMAT_JSON;
return ActiveForm::validate($model);
}
}
/**
* Quick Add Contact Action
* #param type $id
* #return type
*/
public function actionAddContact() {
$model = new ContactsManagement();
if (Yii::$app->request->isAjax && $model->load(Yii::$app->request->post())) {
$transaction = \Yii::$app->db->beginTransaction();
try {
if ($model->validate()) {
$flag = $model->save(false);
if ($flag == true) {
$transaction->commit();
return Json::encode(array( 'status' => 'success', 'type' => 'success', 'message' => 'Contact created successfully.'));
} else {
$transaction->rollBack();
}
} else {
return Json::encode(array('status' => 'warning', 'type' => 'warning', 'message' => 'Contact can not created.'));
}
} catch (Exception $ex) {
$transaction->rollBack();
}
}
return $this->renderAjax('_add_form', [
'model' => $model,
]);
}

Resources