Pass form data to laravel controller using AngularJS - php

I have a simple code here and want to pass data to the laravel controller so I can store it to the database. My codes are:
AccountController.php
public function store(Request $request)
{
Account::create(array(
'email' => $request->get('email'),
'name' => $request->get('text'),
'age' => $request->get('age'),
));
return ['success' => true];
}
Blade
<form ng-submit="newAccount()">
<div class="form-group">
<label for="email">Email address</label>
<input type="email" class="form-control" id="email" ng-model="accountData.email">
</div>
<div class="form-group">
<label for="fullname">Full Name</label>
<input type="email" class="form-control" id="fullname" ng-model="accountData.name">
</div>
<div class="form-group">
<label for="age">age</label>
<input type="email" class="form-control" id="age" ng-model="accountData.age">
</div>
</form>
app.js
var app = angular.module('accountsApp', []);
app.controller('accountsCtrl', function($scope, $http) {
$scope.newAccount = function() {
//add data
$http.post('/api/accounts',
{
//what will I put here to get the textbox values?
}).
.success(function(response) {
scope.accounts = response;
})
.error(function(response) {
console.log(response);
});
};
});
As you can see in my app.js, I'm stuck on how to get the data from the textbox in my blade. Is there an easy way to do this? Thank you.

Pretty easy, you can just add an object to pass with the POST request. Laravel will pick these variables up 1 to 1.
var app = angular.module('accountsApp', []);
app.controller('accountsCtrl', function($scope, $http) {
$scope.newAccount = function() {
//add data
$http.post('/api/accounts',
{
email: $scope.accountData.email,
text: $scope.accountData.text,
age: $scope.accountData.age
}).
.success(function(response) {
scope.accounts = response;
})
.error(function(response) {
console.log(response);
});
};
});

Related

Submitting a form via Fetch API in Laravel

I've been trying to submit the form via a Fetch API, but having no luck so far. I can submit the form without one, but for this exercise it has to be with Fetch.
Form
<form action="{{ url('/process')}}" method="POST">
#csrf
<div class="form-container">
<div class="form-item">
<label for="name">Full Name<span class="required">*</span></label>
<input type="text" name="name" id="name" placeholder="Enter your name" />
</div>
<div class="form-item">
<label for="email">Email<span class="required">*</span></label>
<input type="email" name="email" id="email" placeholder="Enter your email address" required />
</div>
</div>
<div class="form-container">
<button type="submit">Submit</button>
</div>
</form>
^This submits successfully as is, but again I need to use Fetch.
Fetch API:
form.addEventListener("submit", (e) => {
e.preventDefault();
const csrfToken = document.querySelector("input[name='_token']").value;
fetch("success.blade.php", {
method: "post",
body: JSON.stringify(process),
headers: {
"Content-Type": "application/json",
"X-CSRF-Token": csrfToken,
},
})
.then((response) => {
console.log(response);
return response.text();
})
.then((text) => {
return console.log(text);
})
.catch((error) => console.error(error));
}
Routes
Route::get('/', [ContactController::class, 'create']);
Route::get('/all', [ContactController::class, 'getAll']);
Route::post('/process', [ContactController::class, 'store']);
ContactController.php
public function store(Request $request)
{
$contact = Contact::create($request->input());
$message = 'Thank you for your message! We will review your submission and respond to you in 24-48 hours.';
if ($request->ajax()) {
return response()->json(compact('message'));
}
return view('success');
}
success.blade.php is a file I created to display that thank you message, but something tells me I don't need it if I'm using this function store right.
If I remove action="{{ URL('/process') }} , and just use the Fetch API, then I get this error:
The POST method is not supported for this route. Supported methods: GET, HEAD.
you should not send fetch request to the blade
you must send request to controller
change url of fetch with controller

Argument 1 passed to Symfony\Component\HttpFoundation\Response::setContent() with Axios Vue and Laravel 7

I am using Laravel 7 with Vue and Axios and I have run across this error but cannot seem to find out why I am getting it. I am using api routes in my Laravel app for contacts, No Controller and One Contacts Model. I have one vue component named Contacts.vue. When trying to fetch the data for the first time, I am met with a 500 internal server error and when I try to visit the route in question, api/contacts, I am met with the following error:
Argument 1 passed to Symfony\Component\HttpFoundation\Response::setContent() must be of the type string or null, object given, called in C:\laragon\www\contactstore\vendor\laravel\framework\src\Illuminate\Http\Response.php on line 65
To me, as a person new to Laravel, I am not sure how to trace down the problem. Unless there have been changes to axios compared to the way I am trying to use it, I haven't the slightest clue. So, Any help would be greatly appreciated. Thank you.
Here is the Contact.vue
<template>
<div>
<h1>Contacts</h1>
<form
action="#"
#submit.prevent="edit ? updateContact(contact.id) : createContact()"
>
<div class="form-group">
<label for="">Name</label>
<input
v-model="contact.name"
type="text"
name="name"
class="form-control"
placeholder="Enter Contact Name"
/>
</div>
<div class="form-group">
<label for="">Email</label>
<input
v-model="contact.email"
type="email"
name="email"
class="form-control"
placeholder="Enter Contact Email"
/>
</div>
<div class="form-group">
<label for="">Phone</label>
<input
v-model="contact.name"
type="text"
name="phone"
class="form-control"
placeholder="Enter Contact Phone Number"
/>
</div>
<div class="form-group">
<button v-show="!edit" type="submit" class="btn btn-primary">
New Contact
</button>
<button v-show="edit" type="submit" class="btn btn-secondary">
Update Contact
</button>
</div>
</form>
</div>
</template>
<script>
export default {
data: function () {
return {
edit: false,
list: [],
contact: {
id: "",
name: "",
email: "",
phone: "",
},
};
},
mounted: function () {
console.log("Contacts Component Loaded...");
this.fetchContactList();
},
methods: {
fetchContactList: function () {
console.log("Fetching contacts...");
axios
.get("api/contacts")
.then((response) => {
console.log(response.data);
this.list = response.data;
})
.catch((error) => {
console.log(error);
});
},
createContact: function () {
console.log("Creating Contact... ");
let self = this;
let params = Object.assign({}, self.contact);
axios
.post("api/contact/store", params)
.then(function () {
self.contact.name = "";
self.contact.email = "";
self.contact.phone = "";
self.edit = false;
self.fetchContactList();
})
.catch(function (error) {
console.log(error);
});
},
updateContact: function (id) {
console.log("Updating Contact... " + id);
},
},
};
</script>
My Contact model in the Models folder under App
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Contact extends Model
{
//
}
My api.php for the routes
<?php
use App\Models\Contact;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;
Route::get('contacts', function () {
return Contact::latest()->orderBy('created_at', 'desc');
});
Route::get('contact/{id}', function ($id) {
return Contact::findOrFail($id);
});
Route::post('contact/store', function (Request $request) {
return Contact::create([
'name' => $request->input('name'),
'email' => $request->input('email'),
'phone' => $request->input('phone'),
]);
});
Route::patch('contact/{id}', function (Request $request, $id) {
Contact::findOrFail($id)->update([
'name' => $request->input('name'),
'email' => $request->input('email'),
'phone' => $request->input('phone'),
]);
});
Route::delete('contact/{id}', function ($id) {
return Contact::destroy($id);
});
Route::middleware('auth:api')->get('/user', function (Request $request) {
return $request->user();
});
and I am calling it all from within the default welcome.blade.php with
<contacts></contacts>
Again, if you can help me, I would certainly appreciate it. Thank you in advance.
You are returning an Eloquent Builder object from this route:
Route::get('contacts', function () {
return Contact::latest()->orderBy('created_at', 'desc');
});
You can not return this, the framework does not know what to do with this object, you should be executing the query and returning the result:
return Contact::latest()->get();
Then this Collection will get serialized to JSON.
I know this is old, but you could also return dd($variable) to view the content of the returned variable without returning ->first() or ->get().
This could be useful for debugging.

Vue.js not updating URL correctly

Join.vue
<template>
<div class="container join-form">
<form>
<div class="container">
<h2>Join to session</h2>
</div>
<div class="form-group">
<label for="sessionId">Session ID:</label>
<input v-model="sessionId" class="form-control" type="text" name="sessionId" placeholder="Session ID">
</div>
<div class="form-group">
<label for="userName">Username:</label>
<input v-model="userName" class="form-control" type="text" name="userName" placeholder="Your name">
</div>
<button v-on:click.prevent="joinSession()" class="btn btn-primary">Join session</button>
</form>
</div>
</template>
<script>
export default {
data() {
return {
userName: "",
sessionId: this.$route.params.sessionId,
userId: null
};
},
methods: {
joinSession() {
this.$http
.post('/joinsession', {
userName: this.userName,
sessionId: this.sessionId
})
.then(
data => {
this.userId = data.body.userId;
this.$router.push("/user/" + this.sessionId + "/" + this.userId);
},
() => {
this.$router.push("/error");
}
);
}
}
};
</script>
<style>
.join-form {
width: 50%;
}
</style>
I wanna have "/user/{sessionId}/{userId}" but instead I've got
"http://projectx.laragon:8090/user/3/[object%20Object],[object%20Object]"
How can I solve this issue? I am using Laravel in combination with Vue-Resource &% Vue-Router in order to switch between different .vue files that are all together in an App.vue. This means my URL is not actively entered, it is just displayed without fetching from the server.
eg: "user/{userId}/{sessionId}" is a 404 if I didn't register it in my web.php
It seems you actually want do
this.$router.push( { path: '/user', params: { sessionId: this.sessionId, userId: this.userId } });
If it still not work, check your route configuration and sessionId / userId values.
For more info, see the docs

Vue form not sending data in request

I have a form in one component, and I am trying to send data on submit with Ajax request:
<form>
<div class="control">
<input class="input is-large" type="email" v-model="email" required>
<label>E-post</label>
</div>
<div class="control">
<input class="input is-large" type="password" v-model="password" required>
<label>Passord</label>
</div>
<div #click="save" type="submit" class="button hero-button is-medium is-primary">
Logg in
</div>
</form>
This is the method for post request, I am using axios library for Ajax requests:
methods: {
save() {
const form = new FormData();
form.append('email', this.email);
form.append('password', this.password);
this.$backend.post('/user/login', form, {
}).then(() => {
console.log('success');
}, (err) => {
console.log(err);
});
}
}
But, when I check on the backend side, built with laravel, I get an empty request:
{"request":[]}
This is the function in the controller on the backend side:
public function login(Request $request)
{
//testing $request object
return ['request' => $request->all()];
$authenticatedUser = $this->authenticate($request->email, $request->password);
if (!$authenticatedUser) {
$remoteAuthenticated = $this->checkWplUser($request->email, $request->password);
if (!$remoteAuthenticated) {
return $this->response->errorUnauthorized();
}
}
return $this->issueToken($request->email, $request->password);
//return $this->returnUserResponse();
}
This is how the request header looks like:
How can I fix this?

Angularjs Image Upload showing empty nested object

I'm a bit confused how to access file data using with angular from a basic form. I'm following a tut on: (https://uncorkedstudios.com/blog/multipartformdata-file-upload-with-angularjs) and youtube (https://www.youtube.com/watch?v=vLHgpOG1cW4). They seem to get it right but when I try things seem to go a different way. Anyways here's my HTML form:
<form>
<div class="form-group">
<label for="name">Full Name</label>
<input type="text" ng-model="customer.name" id="name" class="form-control"/>
</div>
<div class="form-group">
<label for="email">Email</label>
<input type="email" ng-model="customer.email" id="name" class="form-control"/>
</div>
<div class="form-group">
<label for="file">Image</label>
<input type="file" file-model="customer.file" id="file" class="form-control"/>
</div>
<div class="form-group">
<button type="submit" ng-click="submit()" class="btn btn-primary">Submit</button>
</div>
</form>
And the Directive
app.directive('fileModel', ['$parse', function ($parse) {
return {
restrict: 'A',
link: function(scope, element, attrs) {
var model = $parse(attrs.fileModel);
var modelSetter = model.assign;
element.bind('change', function(){
scope.$apply(function(){
modelSetter(scope, element[0].files[0]);
});
});
}
};
}]);
And finally the controller:
app.controller('CustomerController', ['$scope','CustomerService', function($scope, CustomerService){
$scope.customer = {};
CustomerService.save($scope.customer);
}]);
When I {{ customer }} in my view I'm getting something like this:
{"name":"Robert DeNiro","email":"robie#godfather.com","file":{}}
It's that empty last "file":{} file object that's causing me problems getting values to post to server.
Here's my Customer Service code:
var CustomerService = function($resource) {
return $resource('advertisements/:id', { id: '#_id' }, {
update: {
method: 'PUT' // this method issues a PUT request
},
save: {
method: 'post',
transformRequest: angular.identity,
'Content-Type': undefined
}
});
};
CustomerService.$inject = ['$resource'];
app.service('CustomerService', CustomerService);
I'm using Laravel 5.1 and its reporting validation errors 'required' on all fields suggesting there's an empty object sent through. Thanks in advance.
I have added a submit() method in CustomerController like this:
$scope.submit = function(){
var file = $scope.customer.file;
console.log('file is ' );
console.log(file.name);
console.log($scope.customer.file);
console.dir($scope.customer.file);
};
And in there you can see I've tried experimenting with console.log() and console.dir() and i seem to get the results. For example if i console.log($scope.customer) or console.dir($scope.customer) it gives me the nested file object with all file details. And its looking like this:
> Object {name: "robert deniro", email: "robie#godfather.com", file: File}
> Object
Notice file: File Therefore I'm able to access the file contents/object within the submit() like this: console.log(file.name) or console.log(file.type) or console.log(file.size). I don't know why I was missing it all this time. I hope someone learn from my mistake.
May be that form requires the attribute enctype="multipart/form-data".

Categories