On trying to update data in the array from the modal box. The data is not updated in the dom v-for list.
The following consists of modal and details. The data is entered in the modal box which updates the data in details. The cdata is an array which is updated through out the process. When the data is entered in the modal box. This data is pushed in the cdata. Which should update the details v-for loop but it is not happening rather. I tried updating by listening thru events still there's no effects.
data.vue
export default {
props: ["c-data"],
data: function() {
return {};
},
mounted: function() {},
methods: {}
};
<template>
<button type="button" class="btn btn-primary" data-toggle="modal" data-target="#aModal">Add </button>
<data-detail :cdata="cData"></data-detail>
<add-modal :cdata="cData"></add-modal>
</template>
The following contains code for add modal which updates the data in cData array which is data entered in the data modal.
add-modal.vue
export default {
props: ["c-data"],
data: function() {
return {
cName: "",
cEmail: ""
};
},
mounted() {
console.log(this.cData);
},
methods: {
addC() {
this.cData.push({ cName: this.cName, cEmail: this.cEmail });
console.log(this.cData);
this.$root.$emit("cEvent", this.cData);
}
}
};
<template id="add-modal">
<div class="modal fade" id="aModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog modal-large" role="document">
<div class="modal-content">
<div class="modal-body">
<div class="box">
<div class="row">
<div class="form-group col-sm-6 col-lg-6 col-xl-4">
<div class="input-section">
<input type="text" name="cName" class="form-control" id="c-name" v-model="cName" placeholder="Enter name" value="" required>
<label for="c-name"> Name*</label>
</div>
</div>
<div class="form-group col-sm-6 col-lg-6 col-xl-4">
<div class="input-section">
<input type="text" v-model="cEmail" name="cEmail" class="form-control" id="c-email" placeholder="Enter email" required>
<label for="c-email"> Email*</label>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-outline-primary" data-dismiss="modal">Close</button>
<button type="button" #click="addC" class="btn btn-primary">Save</button>
</div>
</div>
</div>
</div>
</template>
The follow consists of list of v-for which needs to be updated but are not updating.
export default {
props: ["c-data"],
data: function() {
return {};
},
mounted() {
console.log(this.cData);
},
methods: {}
};
<div v-for="(item, i) in cData" :key="item.id">
{{item.name}}
</div>
I have tried to update it thru listening events but no results as cData was already update in the data component.
You should never directly manipulate data that is passed in as a property.
Using events was the right way to go, you just have to de-couple the newly added data from the properties object.
Use
this.$emit("cEvent", { name: this.cName, email: this.cEmail } );
And listen for it in the parent component
<add-modal :cdata="cData" #cEvent="handleNewData"></add-modal>
...
handleNewData(d) {
this.cData.push(d);
}
Your cData object should only be manipulated directly by the actual owner of that data i.e. the parent where the cData object originates from, not in any component where you pass it in as a property.
Full working example that you can use as a reference: https://codesandbox.io/s/n4lk7rmxx4
Related
I'm using below FormulateForm to have input field with the submit button:
<div class="col-12 col-md-3">
<FormulateInput
name="product_codes"
label="Style number"
placeholder="Style number"
/>
</div>
<div class="col-12 col-md-3">
<button
type="button"
class="btn btn-primary"
#click="syncProducts"
>
Sync
</button>
</div>
I want to sent this input data to BE as an array:
<script>
export default {
name: 'SyncProducts',
data() {
return {
styleCodes: [],
}
},
}
</script>
But with this code, instead of Array of String, it sends it as a String.
good day;
i new in laravel and vue.js when i submit form if i have problem in validate one of input it show correctly like The Brand Name field is required. but my real problem is when submitted form successfully when i show response message that i get from controller **i get only one capital** **litter of message appear** only like ***Y*** like "Your Data Added Successfully" but i get the first litter isY` like attached photo that appear how can i solve this problem
thanks
here is my controller
<?php
namespace App\Http\Controllers;
use App\PhoneBook;
use Illuminate\Http\Request;
use Validator;
class PhoneBookController extends Controller
{
/**
* Display a listing of the resource.
*
* #return \Illuminate\Http\Response
*/
public function index()
{
//
return view('phonebook');
}
}
public function add(Request $request)
{
//prepare data for validation
$validationarray=Validator::make($request->all(),
[
'name' => 'required',
'phone' => 'required|min:2|required',
'email' => 'required',
]
,[],[
"name"=>"Brand Name",
'phone' => 'phone',
'email' => 'Email',
]);
if($validationarray->fails())
{
foreach ($validationarray ->messages()->getMessages() as $field_name =>$message):
$response['message']=$message;
endforeach;
$response['status']="failed";
return response()->json($response);
}
// start pass data to model
$branddata=array(
'name' =>$request->name,
'phone' =>$request->phone,
'email' =>$request->email,
);
// start add data
$add=PhoneBook::create($branddata)->id;
if(false !=$add)
{
return response(['status'=>'success',"message"=>"Your Data Added Successfully"]);
}else{
return response(['status'=>'failed',"message"=>"Error Adding data please try again !!"]);
}
}
then my route is
Route::post('phonebook/add',"PhoneBookController#add")->name("cart.deleteProductFromCart");
my view code template
<template>
<div>
<div class="modal fade" id="addData" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">New message</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<span v-if="list.status=='success'" >Record submitted successfully!</span>
<div v-model="list.message" >{{list.message?list.message[0]:''}}</div>
<div class="form-group">
<label for="exampleInputEmail1">Brand Name</label>
<input type="text" name="name" v-model="list.name" class="form-control" id="exampleInputEmail1" placeholder="Example : Kia - Renault">
<p class="help-block">Example : Kia - Renault</p>
</div>
<div class="form-group">
<label class="col-form-label">phone:</label>
<input type="text" name="phone" v-model="list.phone" class="form-control" id="reckipient-name">
<p class="help-block">Example : Kia - Renault</p>
</div>
<div class="form-group">
<label class="col-form-label">email:</label>
<input type="text" class="form-control" v-model="list.email" name="email" id="recikpient-name">
<p class="help-block">Example : Kia - Renault</p>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
<button type="button" class="btn btn-primary" #click="save">Send message</button>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
name: "addData",
data: function () {
return {
list: {
name: '',
phone: '',
email: '',
message:'',
},
}
},
methods: {
save: function () {
axios.post('/phonebook/add',this.$data.list)
.then((response) => this.list.message=response.data.message)
.catch((error) => this.list.message=error.response.data.message)
}
}
}
</script>
<style scoped>
</style>
[![enter image description here][1]][1]
[1]: https://i.stack.imgur.com/sZpDS.png
It's good to pass response as JSON Format
YourXYZController.php
....
$data = new stdClass;
$data->status = "success";
$data->message = "your message";
return response(json_encode($data));
in Vuejs
axios.post('YourXYZController URL', params)
.then(response => {
console.log(response)
})
.catch(error => {
console.log(response)
})
})
And also it's best practice to check request and response in network tab of browser.
For the past few days, I have been following a tutorial about VUE application from a really good youtuber. I was following each and every step as it was mentioned in the tutorial when suddenly I have come to an abrupt halt. This is because the data from my database is not showing up in the frontend. The database does show that I am storing the data properly, and there are no errors whatsoever.
The video where I got stuck on is: https://youtu.be/bUXhGw4aQtA
Here is the code for the index in my controller
public function index()
{
return User::latest()->paginate(10);
}
Here is the app.js
/**
* First we will load all of this project's JavaScript dependencies which
* includes Vue and other libraries. It is a great starting point when
* building robust, powerful web applications using Vue and Laravel.
*/
require('./bootstrap');
window.Vue = require('vue');
import {
Form,
HasError,
AlertError
} from 'vform'
window.Form = Form;
Vue.component(HasError.name, HasError)
Vue.component(AlertError.name, AlertError)
import VueRouter from 'vue-router'
Vue.use(VueRouter)
let routes = [{
path: '/dashboard',
component: require('./components/Dashboard.vue').default
},
{
path: '/profile',
component: require('./components/Profile.vue').default
},
{
path: '/users',
component: require('./components/Users.vue').default
}
]
const router = new VueRouter({
mode: 'history',
routes // short for `routes: routes`
})
/**
* The following block of code may be used to automatically register your
* Vue components. It will recursively scan this directory for the Vue
* components and automatically register them with their "basename".
*
* Eg. ./components/ExampleComponent.vue -> <example-component></example-component>
*/
// const files = require.context('./', true, /\.vue$/i);
// files.keys().map(key => Vue.component(key.split('/').pop().split('.')[0], files(key).default));
Vue.component('example-component', require('./components/ExampleComponent.vue').default);
/**
* Next, we will create a fresh Vue application instance and attach it to
* the page. Then, you may begin adding components to this application
* or customize the JavaScript scaffolding to fit your unique needs.
*/
const app = new Vue({
el: '#app',
router
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<template>
<div class="container">
<div class="row mt-5">
<div class="col-md-12">
<div class="card">
<div class="card-header">
<h3 class="card-title">Users Table</h3>
<div class="card-tools">
<button class="btn btn-success" data-toggle="modal" data-target="#addNew">Add new <i class="fas fa-user-plus"></i></button>
</div>
</div>
<!-- /.card-header -->
<div class="card-body table-responsive p-0">
<table class="table table-hover">
<tbody>
<tr>
<th>ID</th>
<th>Name</th>
<th>Email</th>
<th>Type</th>
<th>Registered At</th>
<th>Modify</th>
</tr>
<tr v-for="user in users.data" :key="user.id">
<td>{{user.id}}</td>
<td>{{user.name}}</td>
<td>{{user.email}}</td>
<td>{{user.type | upText}}</td>
<td>{{user.created_at | myDate}}</td>
<td>
<a href="#" >
<i class="fa fa-edit blue"></i>
</a>
/
<a href="#">
<i class="fa fa-trash red"></i>
</a>
</td>
</tr>
</tbody>
</table>
</div>
</div>
<!-- /.card -->
</div>
</div>
<!-- Modal -->
<div class="modal fade" id="addNew" tabindex="-1" role="dialog" aria-labelledby="addNewLabel" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="addNewLabel">Add Users</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<form #submit.prevent="createUser">
<div class="modal-body">
<div class="form-group">
<input v-model="form.name" type="text" name="name"
placeholder="Name"
class="form-control" :class="{ 'is-invalid': form.errors.has('name') }">
<has-error :form="form" field="name"></has-error>
</div>
<div class="form-group">
<input v-model="form.email" type="text" name="email"
placeholder="email"
class="form-control" :class="{ 'is-invalid': form.errors.has('email') }">
<has-error :form="form" field="email"></has-error>
</div>
<div class="form-group">
<textarea v-model="form.bio" type="text" name="bio"
placeholder="Bio"
class="form-control" :class="{ 'is-invalid': form.errors.has('bio') }"></textarea>
<has-error :form="form" field="bio"></has-error>
</div>
<div class="form-group">
<select v-model="form.type" type="text" name="type"
class="form-control" :class="{ 'is-invalid': form.errors.has('type') }">
<option value="">Select user Role</option>
<option value="user">Employee</option>
<option value="manager">Manager</option>
</select>
<has-error :form="form" field="name"></has-error>
</div>
<div class="form-group">
<input v-model="form.password" type="password" name="password"
placeholder="password"
class="form-control" :class="{ 'is-invalid': form.errors.has('password') }">
<has-error :form="form" field="password"></has-error>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
<button type="submit" class="btn btn-primary">Create</button>
</div>
</form>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
data() {
return {
users: {},
form: new Form({
name: '',
email: '',
password: '',
type: '',
bio: '',
photo: '',
})
}
},
methods: {
loadUsers() {
axios.get("api/user").then(({
data
}) => (this.user = data));
},
createUser() {
this.form.post('api/user');
}
},
created() {
this.loadUsers();
}
}
</script>
Please let me know if any other code is required for me to elaborate on the query that I have here. I have tried all options that I could think of and search and couldn't get it to work. Hopefully, another set of eyes can help me figure out the problem.
I expect a full table showing all the rows from my database, and the front-end shows nothing. (Note: I did check the network tab in the developer's options in Chrome and there was only a single xhr type and it showed status 200).
I suggest you go on youtube to search for laravel/vue tutorials, there are tons of good resources there that can help you.
For what you are trying to achieve, if you have mounted your component well and can see a dummy test in the component on your browser, then you are half way done.
Inside your mounted hook of your vue component, make an api call to your backend (laravel) to fetch users like so;
axios.get('/get_all_users').then((res)=>{
this.users = res.data
//do a console.log(res.data) to ensure you are getting the users collection
}).catch((err) => {
console.log(err)
});
Inside your data object, create an empty array that holds your users like so;
data(){
return{
users: []
}
}
Now, inside your web.php, create a GET route for this api call;
ROUTE::get('/get_all_users', 'UsersController#FetchUsers');
Note that your controller and method necessarily not be named as above, create a controller, and inside, write a method to fetch users and use them here asap;
Inside your controller, write your method;
public function FetchUsers(){
$users = User::latest()->get();
return response()->json($users, 200);
}
Also note that you will need to import your User model at the top of the controller file like so;
use App\User;
Also ensure before now that you have the User model created that relates to your users table;
By now you should see the arrays of users on your browser developer tool console if everything is fine.
Then in your template, iterate through the users data like so;
<tr v-for="user in users" :key="user.id">
<td>{{ user.id }} </td>
<td>{{ user.name }} </td>
<td>{{ user.email }} </td>
<td>{{ user.created_at }} </td>
</tr>
I will be glad to help in case you need further clarifications.
You need to return your data as json. You can use Laravel [Resource]
(https://laravel.com/docs/5.8/eloquent-resources)
Create user resource
php artisan make:resource User
User Controller
use App\Http\Resources\User as UserResource;
On your Method
$user = User::latest()->paginate(10);
return UserResource::collection($user)
I have a Vue component that has a 'select state' dropdown element. I want to add a js function that populates the options with the 50 states instead of having to hard code them. I will also have this dropdown in a couple other places so I want this function to be accessed from outside the component. What is the best way to accomplish this?
<template>
<div class="section" v-bind:class="sectionClass" data-mh="group3">
<h3>{{sectionTitle}}</h3>
<div class="section-content display-area">
<i class="icon icon-health img-left"></i>
<form>
<div class="row mt">
<div class="col-xs-12 col-sm-8">
<div class="same-height-parent">
<div class="same-height">
<input type="text" class="form-control" placeholder="Enter Name">
</div>
<div class="same-height">
<select name="state" id="state" class="form-control" tabindex="9">
<option value="">- Select State -</option>
</select>
</div>
</div>
<!-- same-height-parent -->
</div>
<div class="col-xs-12 col-sm-4">
<button type="submit" class="btn btn-success btn-block btn-fz20">Search</button>
</div>
</div>
</form>
</div>
</div>
</template>
<script>
export default {
name: 'nameSearch',
data: function() {
return {
sectionTitle: 'Name Search'=
}
}
}
</script>
you may want to export the function from some other file, this is simply a case of declaring it the way you want.
in some other file...
// utils.js
export function createOptions (someArg) {
let options = [ ... ]
return options
}
in your .vue file
<script>
import { createOptions } from './utils'
export default {
...
data () {
return {
options: createOptions()
}
}
}
</script>
You may also want to try snovakovic's advice to externalise the dropdown component instead, whatever brings you more flexibility
Why not just create states components that handles drop-down and then include that component everywhere where it's used.
If you want just a function then create js file that expose that function and than import that file inside component.
I am trying to edit and delete a data in Mongo.Collection. I have a document with a number of fields including an email address.
I check while updating the data if email exists just update the email else first create a user with that email using Accounts.createUser and then update the data. Although the data is being updated successfully in the database but showing it using the helpers is not working properly. I am trying to fill the form with the saved values, either form comes half-filled, or completely-filled(usually in the first edit attempt) or completely empty. I cannot understand the reason behind this beviour.
The form template
<template name="addUnit">
<div class="modal fade" id="addUnitModal" tabindex="-1" role="dialog">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
<h4 class="modal-title">{{#if isEdit}}Edit {{else}}Add {{/if}}Unit</h4>
</div>
{{#if tenantError}}
<div class="alert alert-danger" role="alert">{{tenantError}}</div>
{{/if}}
<form class="frmUnit" id="frmUnit">
<div class="modal-body">
<input class="form-control" type="text" placeholder="Unit Name" name="unitName" value="{{selectedUnit.unitName}}"/>
<input class="form-control" type="number" placeholder="Number of Residents" name="residents" value="{{selectedUnit.residents}}"/>
<input class="form-control" type="number" placeholder="Area sqft." name="area" value="{{selectedUnit.area}}"/>
<input class="form-control" type="text" placeholder="Primary Tenant" name="primaryTenant" value="{{selectedUnit.primaryTenant}}"/>
<input class="form-control" type="email" name="tenantEmail" placeholder="Tenant's Email" value="{{selectedUnit.tenantEmail}}"/>
<input class="form-control" type="password" name="tenantPassword" placeholder="Tenant's Password"/>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
{{#if isEdit}}
<button type="submit" class="btnEditUnit btn btn-primary">Edit Unit</button>
{{else}}
<button type="submit" class="btnAddUnit btn btn-primary">Add Unit</button>
{{/if}}
</div>
</form>
</div>
</div>
</div>
</template>
Helpers
Template.addUnit.helpers({
isEdit: function() {
return Session.get('isEdit');
},
tenantError: function(){
return Session.get('tenantError');
},
selectedUnit: function(){
return Session.get('selectedUnit');
}
});
Events
Template.addUnit.events({
"submit .frmUnit": function(event){
event.preventDefault();
var form = event.target;
if(!Session.get('isEdit')){
console.log('adding');
Meteor.call('addUnit',
Session.get('selectedBuilding')._id,
{
unitName: form.unitName.value,
primaryTenant: form.primaryTenant.value,
tenantEmail: form.tenantEmail.value,
tenantPassword: form.tenantPassword.value,
residents: form.residents.value,
area: form.area.value
}, function(error, result) {
console.log(error, result);
if(!error){
$('#frmUnit')[0].reset();
$('#addUnitModal').modal('hide');
Session.set('tenantError', null);
}else{
Session.set('tenantError', error.reason);
}
});
}else{
console.log('editing');
Meteor.call('editUnit',Session.get('selectedUnit')._id,{
unitName: form.unitName.value,
primaryTenant: form.primaryTenant.value,
residents: form.residents.value,
area: form.area.value,
tenantEmail: form.tenantEmail.value,
tenantPassword: form.tenantPassword.value
}, function(error, result) {
if(!error) {
$('#frmUnit')[0].reset();
$('#addUnitModal').modal('hide');
}else{
Session.set('tenantError', error.reason);
}
});
}
}
});
Edit unit on the server
editUnit: function(unitId, unit){
//if the email entered already exists update the email and password
var updatedTenant = Accounts.findUserByEmail(unit.tenantEmail);
if(updatedTenant){
if(unit.tenantPassword && unit.tenantPassword !== ""){
Accounts.setPassword(updatedTenant._id, unit.tenantPassword);
}
Units.update({_id: unitId},
{
$set :{
unitName:unit.unitName,
primaryTenant:unit.primaryTenant,
residents: unit.residents,
area: unit.area,
tenantEmail: unit.tenantEmail
}
});
}else{
//if email doesn't exist already, create a new user first
var newUserId = Accounts.createUser(
{
email: unit.tenantEmail,
password: unit.tenantPassword,
profile:{
firstname: unit.primaryTenant,
lastname:"",
phone:"",
isTenant:true
}
});
if(newUserId){
Units.update({_id: unitId},
{
$set :{
unitName:unit.unitName,
primaryTenant:unit.primaryTenant,
residents: unit.residents,
area: unit.area,
tenantEmail:unit.tenantEmail
}
});
}
}
},
Session.get('selectedUnit') is being set from a different click handler, which displays the form. The value is being set correctly I can see that by logging it to the console.
'isEdit' is also being set from a click handler of a different template.
I have other forms working with the same approach, but they don't have Account creation and validation in them. Is it because of that?
Edit
Template.owner.events({
"click .editUnit":function(){
Session.set('isEdit', true);
Session.set('selectedUnit', this);
}
});
{{#each buildingUnits}}
<tr>
<td>
{{unitName}}
</td>
<td>
<span class= "editUnit list-icon glyphicon glyphicon-edit" data-target="#addUnitModal" data-toggle="modal" aria-hidden="true" style="padding-right: 4px;"></span>
<span class= "deleteUnit list-icon glyphicon glyphicon-remove" aria-hidden="true"></span>
</td>
</tr>
{{/each}}
I have tried to log this onto the console, I am getting the correct result, just after the two lines I tried to get the session back using Session.get('selectedUnit') and tried logging it to console, this also gives me the correct result, which means session is being successfully set.