Angularjs Image Upload showing empty nested object - php

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".

Related

How do I send an image to a PHP API using VueJS?

I am trying to send an object which contains an image using Vue to a PHP API but honestly I don't know how,
I have my form
<form #submit='sendData'>
<div class="input-group">
<label for="name">Name</label>
<input type="text" #change="getText" name='text' id='text'>
</div>
<div class="input-group">
<label for="photo">Photo</label>
<input type="file" #change="getImage" name='photo' id='photo'>
</div>
</form>
export default{
data(){
return {
myData:{
text:'',
photo:''
}
}
}
and the getImage() like this
getImage(event){
let formData = new formData();
formData.append('photo',event.target.files[0]);
this.myData.photo=formData;
}
getText(event){
this.myData[event.target.name]=event.target.value;
}
sendData(event){
event.preventDefault();
this.$http.post('myapi/api/user',this.myData);
}
I don't know how to access this image in my PHP API and upload it to database.
I tried accessing $_FILES but it's an empty array
Sorry seems the problem is that I am sending some other data too and not only the formData
if you want to send an image to an api.
You form should specify the type de data you must send for
your form. you should add this.
<form enctype="multipart/form-data">
<input type="text" class="form-control" v-model="myData.text" />
<input type="file" class="form-control" #change="handleUpload($event.target.files)" />
</form>
In your script you need to set this methods
data () {
return {
myData: {
text: '',
photo: null
}
}
},
methods: {
handleUpload(files) {
this.myData.photo = files[0];
},
saveProductImage () {
let formData = new FormData()
formData.append('text', this.myData.text);
formData.append('photo', this.myData.photo);
// Send here
}
}
Please check the docs

laravel api ajax form wont submit

This is my first api project. Can you help me with my code please?
I can't see the problem.
Here is my controller.
public function store(Request $request)
{
//
$valid=Validator::make($request->all(),[
'text'=>'required',
'body'=>'required'
]);
if($valid->fails()){
return response()->json(['message'=>$valid->messages()]);
}else{
$item= Item::create([
'text'=>$request->input('text'),
'body'=>$request->input('body')
]);
return response()->json($item);
}
}
and here is my form.Is there anything wrong in the form?
<form id="form">
<div class="form-group">
<label>Text :</label>
<input type="text" id="text" class="form-control col-sm-4">
</div>
<div class="form-group">
<label>Body :</label>
<textarea id="body" class="form-control col-sm-4"></textarea>
</div>
<div class="form-action">
<input type="submit" class="btn btn-primary" value="submit">
</div>
</form>
and the ajax code between the show function is working but I don't know where the problem is ?.
$('#form').on('submit', function (e) {
e.preventDefault();//prevent the form to submit to file
let text = $('#text').val();
let body = $('#body').val();
addItems(text, body);
});
function addItems(text, body) {
var item = {
text: text,
body: body
};
$.ajax({
method: 'POST',
url: 'http://localhost:8000/api/items',
data: item,
success: function (item) {
alert('done the item number' + item.id + ' has been added!!');
location.reload();
},
error: function () {
alert('error')
}
})
}
Thanks for helping!
if your front-end source separated from back-end source, then add cross-Origin Resource Sharing
package to your laravel project.
if its on your laravel view then add csrf token to meta tag -
<meta name="csrf-token" content="{{ csrf_token() }}">
and send it with your ajax request { _token : document.querySelector('meta[name="csrf-token"]').content}
The problem is that you're sending the form without sending the cross site request forgery token.
Add the directive #csrf to your view
Then send it has Hasan wrote ;)

Controller not getting inputs laravel

Currently I am trying to pass a creation form to a controller. I have the route and the ajax call setup and talking to the route. My problem is that when I use the ajax call the inspect tool for headers is showing my form values correctly but when I go into the controller the request->input doesnt show any values for the form.
Here is my ajax call
$(document).on("click", ".form-submit-btn", function() {
// Get the form id.
var formID = $(this).closest("form").attr("id");
var serializedForm = $(this).closest("form").serialize();
var substringEnd = formID.indexOf("-form");
var route = formID.substr(0, substringEnd).replace("-", "_");
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
});
// Submit the form.
$.ajax({
method: "POST",
url: "/" + route,
data: {
serializedForm
},
success: function(data) {
alert(data);
}
});
});
Here is my controller
// Create Role
public function create(Request $request)
{
// Get and validate request params
$role = $request->input('role_name');
$active = $request->input('role-active', false);
return $role;
}
And here is my route
Route::post('/create_role', 'RoleController#create');
Am I missing something that is preventing the ajax call from sending the values to the controller
Here is my form also if that helps.
<form id="create-role-form" class="form">
{{ csrf_field() }}
<button class="pull-right right-close-btn">X</button>
<h1>Add Role</h1>
<hr />
<div class="form-group">
<label>Role Name</label>
<input type="text" name="role_name" class="form-control" />
</div>
<div class="form-group">
<input type="checkbox" name="role_active" value="true" checked /> Active
</div>
<div class="form-group">
<button class="btn btn-primary form-control form-submit-btn">Create</button>
</div>
I think problem is this line
data: {serializedForm},
Just change it to
data: serializedForm,
and it should fix the problem.
Problems
I see two problems with your ajax request
Are you sure you're using ES-6 TransPiler because data:{serializedForm}, is ES-6 Syntax http://es6-features.org/#PropertyShorthand
If you're javascript is working fine. You should be able to get it like $request->get('serializedForm')['role_name'] with your existing code.
Hope it helps

AJAX sends null values

Register form:
{!! Form::open(['route' => 'api.register', 'method' => 'post', 'id' => 'register_form']) !!}
<div class="form-group">
<div class="inputer">
<div class="input-wrapper">
<input id="register_name" type="text" class="form-control" placeholder="Enter your full name">
</div>
</div>
</div>
<!--.form-group-->
<div class="form-group">
<div class="inputer">
<div class="input-wrapper">
<input id="register_email" type="email" class="form-control" placeholder="Enter your email address">
</div>
</div>
</div>
<!--.form-group-->
<div class="form-group">
<div class="inputer">
<div class="input-wrapper">
<input id="register_pass" type="password" class="form-control" placeholder="Enter your password">
</div>
</div>
</div>
<!--.form-group-->
<div class="form-group">
<div class="inputer">
<div class="input-wrapper">
<input id="register_confirm" type="password" class="form-control" placeholder="Enter your password again">
</div>
</div>
</div>
<!--.form-group-->
<div class="form-group">
<label>
<input type="checkbox" name="remember" value="1"> I have read and agree to the term of use.
</label>
</div>
<div class="form-buttons clearfix">
<button class="btn btn-white pull-left show-pane-login">Cancel</button>
<button id="register_submit" class="btn btn-success pull-right">Sign Up</button>
</div>
<!--.form-buttons-->
{!! Form::close() !!}
JS:
$("#register_form").submit(function(e) {
e.preventDefault();
});
$('#register_submit').click(function()
{
var address = $('#register_form').attr('action');
var method = $('#register_form').attr('method');
var user_name = $('#register_name').val();
var mail = $('#register_email').val();
var pass = $('#register_pass').val();
var pass_confirm = $('#register_confirm').val();
var name = $("input[name=_token]").val();
$.ajax({
url: address,
type: method,
data:
{
name: user_name,
email: mail,
password: pass,
password_confirm : pass_confirm,
_token: name
},
success:function(response) {
alert(response);
},
error:function(response) {
alert(response);
},
});
});
Route:
Route::post('/processregister', ['as' => 'api.register', 'uses' => 'AuthController#register']);
Register function:
public function register(Request $request)
{
return $request->name;
}
At webportal.dev/processregister it gives blank page. It means request parameters sends remains null. Where I am going wrong?
(Maybe conflicts? There is also a login form on same page but it is submitted by seperate function and that login form works correctly.)
It's due to a very common mistake in Submit button.
A button <button> with type=submit will submit the form by default, unless you stop the default behavior via event.preventDefault() in your $('#register_submit').click() function. The default behavior runs before your AJAX call is responded and forwarded to the URL in action attribute specified in <form> tag (i.e. http://webportal.dev/processregister)
In your case, you can also change the type of the button to button to avoid this form submission behavior.
Remove type="submit" in this line:
<button id="register_submit" type="submit" class="btn btn-success pull-right">Sign Up</button>
Also be sure that your ajax code is really called.
Based on the comments the issue was due to your view being cached. Since i was able to run the exact same code to generate the result intended. Next time try to run php artisan view:clear to clear the cached views as the first step in debugging view errors. Also always post the code used when seeking help and not the code being generated.
Another tip is to assign names instead of id to the form inputs and then serialize the form data in the ajax request. You save all the work of fetching the value of each input by it's id and then using it.
Why not moving all your code inside your .submit function, and just add return false; at the end?
$("#register_form").submit(function(e) {
var address = $('#register_form').attr('action');
var method = $('#register_form').attr('method');
var user_name = $('#register_name').val();
var mail = $('#register_email').val();
var pass = $('#register_pass').val();
var pass_confirm = $('#register_confirm').val();
var name = $("input[name=_token]").val();
$.ajax({
url: address,
type: method,
data:
{
name: user_name,
email: mail,
password: pass,
password_confirm : pass_confirm,
_token: name
},
success:function(response) {
alert(response);
},
error:function(response) {
alert(response);
},
});
return false;
});
Please then watch what happens with your ajax request in the Developer Tools (F12) > Network tab. Perhaps there is an error on the server side.

UserFrosting forms - Invalid or missing CSRF token

I am trying to submit a simple form in UserFrosting and as a test only display the success message, with no data modification. I followed the guidance from Lesson 2 but I ran into the CSRF issue:
UserFrosting returns the following error:
Invalid or missing CSRF token.
What am I missing? Up until this point UserFrosting was very easy to digest :(
The form:
<form class="form-horizontal" role="form" name="requestDescription" action="{{site.uri.public}}/soap/requests/desc/edit/{{ keyname }}" method="post">
<div class="form-group">
<label for="input_group" class="col-md-2 control-label">Name</label>
<div class="col-md-10">
<input type="text" id="input_name" class="form-control" name="lgname" placeholder="{{ name }}">
</div>
</div>
<div class="form-group text-center">
<button type="submit" class="btn btn-success text-center">Update</button>
</div>
</form>
with added script part to the bottom of the twig file:
<script>
$(document).ready(function() {
// Load the validator rules for this form
var validators = {{validators | raw}};
ufFormSubmit(
$("form[name='requestDescription']"),
validators,
$("#userfrosting-alerts"),
function(data, statusText, jqXHR) {
// Reload the page on success
window.location.reload(true);
}
);
});
</script>
Here are my two functions from the controller:
public function soapRequestDescriptionEditPage($keyname){
if (!$this->_app->user->checkAccess('uri_soap_requests')){
$this->_app->notFound();
}
$requestDetails = $this->soapRequestReadMeta($keyname);
$schema = new \Fortress\RequestSchema($this->_app->config('schema.path') . "/forms/soap-request-description-edit.json");
$this->_app->jsValidator->setSchema($schema);
$this->_app->render('soap/soap-request-description-edit.twig', [
"name" => $requestDetails['name'],
"description" => $requestDetails['description'],
"keyname" => $keyname,
"validators" => $this->_app->jsValidator->rules()
]);
}
public function test(){
if (!$this->_app->user->checkAccess('uri_soap_requests')) {
$this->_app->notFound();
}
$post = $this->_app->request->post();
$ms = $this->_app->alerts;
$requestSchema = new \Fortress\RequestSchema($this->_app->config('schema.path') . "/forms/soap-request-description-edit.json");
$rf = new \Fortress\HTTPRequestFortress($ms, $requestSchema, $post);
$ms->addMessageTranslated("success", "Everyone's title has been updated!", $post);
$rf->sanitize();
if (!$rf->validate()) {
$this->_app->halt(400);
}
$data = $rf->data();
}
Entries from the index.php file:
$app->post('/soap/requests/desc/edit/:request_id/?', function () use ($app) {
$controller = new UF\SoapController($app);
return $controller->test();
});
$app->get('/soap/requests/desc/edit/:request_id/?', function ($request_id) use ($app) {
$controller = new UF\SoapController($app);
return $controller->soapRequestDescriptionEditPage($request_id);
});
Finally, the schema:
{
"lgname" : {
"validators" : {
"length" : {
"min" : 1,
"max" : 150,
"message" : "The new title must be between 1 and 150 characters long."
}
},
"sanitizers" : {
"raw" : ""
}
}
}
As of UserFrosting 4, you should explicitly add the hidden CSRF input fields to your form. There is a partial template forms/csrf.html.twig that contains these fields, which you can insert using Twig's include tag:
<form class="form-horizontal" role="form" name="requestDescription" action="{{site.uri.public}}/soap/requests/desc/edit/{{ keyname }}" method="post">
{% include "forms/csrf.html.twig" %}
<div class="form-group">
<label for="input_group" class="col-md-2 control-label">Name</label>
<div class="col-md-10">
<input type="text" id="input_name" class="form-control" name="lgname" placeholder="{{ name }}">
</div>
</div>
<div class="form-group text-center">
<button type="submit" class="btn btn-success text-center">Update</button>
</div>
</form>
For requests that are made without a form (for example, if it has been constructed purely in Javascript), you can grab the CSRF token name and value from the global site.csrf variable:
var userName = 'luke';
var fieldName = 'lgname';
var data = {
'value': fieldValue
};
data[site.csrf.keys.name] = site.csrf.name;
data[site.csrf.keys.value] = site.csrf.value;
var url = site.uri.public + '/api/users/u/' + userName + '/' + fieldName;
return $.ajax({
type: "PUT",
url: url,
data: data
}).done(function (response) {
window.location.reload();
});
It turned out that my code was fine. There were unrelated javascript errors on the page affecting UserFrosting form processing. Fixing these errors allowed UserFrosting to handle the form.
Note to self... make it a habit to look into the console for javascript errors :)

Categories