Better Way to use Laravel old and Vue.js - laravel

Im working using vue.js 2.0 and Laravel 5.4 I would like to know if exits a better way to send data Controllers -> views without lost the value, overwrite by the v-model
Because after charge vue.js this take the value in data that is define in this way
data: {
ciudad:'',
}
If I try to do something like that
<input class="form-control" id="ciudad" name="ciudad" type="text" v-model="documento.ciudad" value="{{ $documento->ciudad }}" >
I lost the value sending by the controller

Vue really expects you to init data from the view model which then updates the view, however, you want to use data in the view to update the underlying model data.
I think the easiest approach to this is to write a directive that inits the value from the HTML, so you don't need to directly access the DOM:
Vue.directive('init', {
bind: function(el, binding, vnode) {
vnode.context[binding.arg] = binding.value;
}
});
It's a little abstract so it's worth looking at Directive Hook Arguments section of the docs.
This can then be used like:
<input v-model="ciudad" v-init:ciudad="'{{ old('ciudad') }}'">
Here's the JSFiddle: https://jsfiddle.net/v5djagta/

The easy way to do this for me was in this way:
Laravel Controller
$documento = ReduJornada::where("id_documento",$id)->first();
return view('documentos.redujornada')->with(compact('documento'));
Laravel View
<input class="form-control" id="ciudad" v-model="documento.ciudad" value="{{ old('ciudad', isset($documento->ciudad) ? $documento->ciudad : null) }}" >
Vue.js
data: {
ibanIsInvalid : false,
documento: {
ciudad: $('#ciudad').val(),
}
In this way I can use the same view to create and edit an object, using the same form, even use laravel validation without lost the data after refresh.
If you know a better way to do that please tell me... Thanks

You have to define your value first, for example :
$oldValue = $request->old('value');
and then pass it to vue component, define props and use it in v-model
<script>
export default {
props: {
$oldValue : String,
}
};
</script>
<template>
<input class="form-control" id="ciudad" name="ciudad" type="text" v-model="oldValue">
</template>

Related

Laravel Livewire, form submit: do something first then submit the form

I have a livewire form which I intent to submit to an external url. However, before submitting, I want to programmatically add some hidden inputs which the user should not be able to edit then finally submit the form:
<form action="some-external-url" wire:submit.prevent="processForm" method="post">
<x-inputs.text-input wire:model="amount" name="amount" />
<x-inputs.button title="Submit" />
</form>
Something similar to this jQuery code:
$('form').submit( function(ev){
ev.preventDefault();
//fetch and add some additional fields to the form
// finally submit the form
$(this).unbind('submit').submit()
});
How best can I achieve this using livewire. Please note that I dont intent to use guzzle to submit this form.
If you want in your component you can set the properties, you need and then in your mount method, you initialise the value for those properties.
see forms in livewire
class ComponentName extends Component
{
public $hidden_val;
public function mount()
{
$this->hidden_val = "my_hidden_val";
}
}
Then pass it with livewire
<input type="hidden" wire:model="hidden_val">
But I also think as #ClémentBaconnier and would suggest to pass to external link the data of form using Http Client provided by laravel in your controller or event within your livewire component.
Http::asForm()->post('some-external-url', ['form_data' => /*your form data*/]);
Follow it here

Get Data back from Vue Component

Is it possible to get Data back from a vue component?
Laravel blade.php code:
...
<div>
<component1></component1>
</div>
...
In component1 is a selectbox which i need (only the selected item/value) in the blade.php
A vue component, when rendered in the browser, is still valid HTML. If you make sure your component is wrapped in a form element and has a valid input element, and the form can be submitted, the PHP endpoint can consume the form’s data without problems. It could look like this:
Layout/view:
<form method="post" action="/blade.php">
<component1></component1>
<button type="submit">Submit form</button>
</form>
Component (<component1/>):
<fieldset>
<input type="checkbox" name="my_option" id="my_option">
<label for="my_option">I have checked this checkbox</label>
</fieldset>
PHP script (blade.php):
echo $_POST["my_option"] // if checked, should print "on"
If you are looking for a JavaScript centered approach, you may want to serialize the form and fetch the endpoint; it could look similar to this:
import serialize from 'form-serialize';
const formData = serialize(form)
fetch(form.action, { method: 'POST' }, body: JSON.stringify(formData) })
.then(response => {
// update page with happy flow
})
.catch(error => {
// update page with unhappy flow
})
Building from an accessible and standardized basis using proper HTML semantics will likely lead to more understandable code and easier enhancements down the road. Good luck!
(Edit: if you require a complete, working solution to your question, you should post more code, both from the Vue app as well as the PHP script.)

What is the best way to use v-model without using it in the main app.js file?

I was wondering i have this code inside my blade file:
<input type="text" class="form-control" :model="productname" id="name" name="name" aria-describedby="emailHelp" placeholder="Title" value="{{ old('name') }}" required>
and i want to create an 2 way data binding, so when user submitted 3 or more character to get an green background of this input field, but when they are less to get a red background.
I tried to do this with vue-component, but it seems for whatever reason the vue-component does not have access to the main #app id which is assign to the main app blade template in order all vue code to have access to the html code and change it. I have created an vue-component called Upload inside ressources/assests/js/components/Upload.js, but when i write this code:
<template>
</template>
<script>
export default {
data() {
return {
productname: '',
};
},
mounted() {
console.log('Upload component', this.message);
}
}
</script>
and added of course to app.js like that Vue.component('upload-component', require('./components/Upload.vue'));
and run - npm run dev to compile the code i am getting this error:
[Vue warn]: Property or method "productname" is not defined on the instance but referenced during render. Make sure that this property is reactive, either in the data option, or for class-based components, by initializing the property. See: https://v2.vuejs.org/v2/guide/reactivity.html#Declaring-Reactive-Properties.
Whatever when i write this code inside the main app.js file (resources/assests/js/app.js):
const app = new Vue({
el: '#app',
data() {
return {
productname: '',
};
},
});
everything is working fine and i dont get any errors, but i dont want that, as imagine for my website/app i have to have for example 100 v-models and i dont want to put them all inside the main app.js file. Is there other way to do this?
Can i still somehow make it work inside the vue component, so the component can see the v-model and not giving me this error?
If not, can i make it work and use vue inside the blade file something like that?
new Vue({
el: '#form',
data: {
productname: ''
}
});
but this code its not working. Thanks!
It's a bit tricky to make out what you are doing exactly, but your error is related to having no data property 'message', you have only a property called 'productname'.
If you want your component to communicate up to its parents or siblings you should read into emitting events in vue using
this.$emit

Resetting a form generated server-side in vue.js

I am rendering a form with Blade, Laravel's server-side templating language. The default values for the form elements are assigned by Blade. There is no JavaScript involved until now. Now I want to implement a reset button.
When a user presses the reset button the form should be cleared. A simple HTML reset button is not sufficient as it would not reset the "value=something" default values to "null".
In other words:
<input type="text" name="fullname" value="John Doe">
is supposed to be
<input type="text" name="fullname" value="">
after the user pressed the reset button.
With JQuery I would do something like this:
$("body").find('form').find('input').val('');
How can I do it with vue.js? Adding av-model and setting the v-model properties to null interferes with the server side default values...
In general: would you suggest to add a DOM manipulating lib to the application for such "hybrid" use cases where vue.js does not control the data?
If you plan on using vue, forget about altering the dom, vue works around states so imagine your input is like this
<input type="text" v-model="test_input">
and when you change the variable test_input the input automaticly changes its value, so just set it to empty in a method.
<button #click="clear_form"> Clear </button>
<script>
export default {
data() {
return {
test_input : ''
}
},
methods:{
clear_form(){
this.test_input = '';
}
}
}
</script>
I ended up writing a reset-form button component. In this component I use plain Javascript to get all input, select, ... fields of the form identified by an id and reseted the values to ''.
I took this option as it was the fastest way to reset the form and I don't have to change anything (e.g. add props, change ajax calls) if my form changes.

How does Laravel handle PUT requests from browsers?

I know browsers only support POST and GET requests, and Laravel supports PUT requests using the following code:
<?= Form::open('/path/', 'PUT'); ?>
... form stuff ...
<?= Form::close(); ?>
This produces the following HTML
<form method="POST" action="http://example.com/home/" accept-charset="UTF-8">
<input type="hidden" name="_method" value="PUT" />
... form stuff ...
</form>
How does the framework handle this? Does it capture the POST request before deciding which route to send the request off to? Does it use ajax to send an actual PUT to the framework?
It inserts a hidden field, and that field mentions it is a PUT or DELETE request
See here:
echo Form::open('user/profile', 'PUT');
results in:
<input type="hidden" name="_method" value="PUT">
Then it looks for _method when routing in the request.php core file (look for 'spoofing' in the code) - and if it detects it - will use that value to route to the correct restful controller.
It is still using "POST" to achieve this. There is no ajax used.
Laravel uses the symfony Http Foundation which checks for this _method variable and changes the request to either PUT or DELETE based on its contents. Yes, this happens before routing takes place.
You can also use an array within your form open like so:
{{ Form::open( array('route' => array('equipment.update', $item->id ),
'role' => 'form',
'method' => 'put')) }}
Simply change the method to what you want.
While a late answer, I feel it is important to add this for anyone else who finds this and can't get their API to work.
When using Laravel's resource routes like this:
Route::resource('myRoute','MyController');
It will expect a PUT in order to call the update() method. For this to work normally (outside of a form submission), you need to make sure you pass the ContentType as x-www-form-urlencoded. This is default for forms, but making requests with cURL or using a tool like Postman will not work unless you set this.
PUT usually refers to update request.
When you open a form inside laravel blade template using,
{{ Form::open('/path/', 'PUT') }}
It would create a hidden field inside the form as follows,
<input type="hidden" name="_method" value="PUT" />
In order for you to process the PUT request inside your controller, you would need to create a method with a put prefix,
for example, putMethodName()
so if you specify,
{{ Form::open('controller/methodName/', 'PUT') }}
inside Form:open. Then you would need to create a controller method as follows,
class Controller extends BaseController {
public function putMethodName()
{
// put - usual update code logic goes here
}
}

Resources