I just created a symbolic link using this command php artisan storage:link to be able to access my files from the web. I've known this from Laravel's official docs: https://laravel.com/docs/5.3/filesystem#configuration.
And so I'm using <img src="{{ Storage::url($user->avatar) }}"> in my blade template to get the path of my image.
My question is, how can I achieve similar approach using VueJS Template?
I tried <img src="{{ Storage::url($user->avatar) }}"> in my .vue file but got an error when running gulp watch. The error throws an invalid expression. Simple means I can't use Laravel's Facades inside a .vue file?
What would be the best approach in getting the correct path of my image then? Use $avatar = Storage::url($user->avatar); and inject it to an array before getting it in .vue file?
For reference here's my:
VueJS File
<template>
<div class="row">
<div class="col-md-4" v-for="person in people">
<div class="panel panel-default">
<div class="panel-heading text-center">
{{ person.name }}
</div>
<div class="panel-body">
<img :src="person.avatar" class="img-responsive">
</div>
</div>
</div>
</div>
</template>
<script>
export default {
mounted() {
this.$http.get('/people/')
.then((res) => {
console.log(res)
this.people = res.body.people
})
},
data() {
return {
people: '',
}
}
}
</script>
Route
Route::group(['prefix' => 'people', 'middleware' => ['auth']], function () {
Route::get('/', [
'uses' => 'PeopleController#index',
'as' => 'people',
]);
});
Controller
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\User;
class PeopleController extends Controller
{
public function index () {
$people = User::all();
return response()->json(['people' => $people]);
}
}
Why not set the storage path in your User model.
Create an avatar_url attribute in your model.
use Illuminate\Support\Facades\Storage;
class User extends Model {
protected $appends = ['avatar_url'];
....
public function getAvatarUrlAttribute() {
return Storage::url($this->avatar);
}
...
}
Then in your VueJS file...
<img :src="person.avatar_url" class="img-responsive">
Related
I have some quotes in a database and am trying to use Laravel to display it on a page. I have the quotes being pulled from the controller then passed to the view but I am getting an error:
Undefined variable: quotes (View: C:\laragon\www\resources\views\inc\quote.blade.php) (View: C:\laragon\www\\resources\views\inc\quote.blade.php) (View: C:\laragon\www\\resources\views\inc\quote.blade.php
QuotesController.php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use App\Http\Controllers\Controller;
class QuotesController extends Controller
{
public function index()
{
$quotes = DB::table('quotes')->get();
return view('inc.quote', ['quotes' => $quotes]);
}
}
quote.blade.php
<div id="MarketingQuote" class="container-fluid padding bg-light">
<div class="row">
<div class="col-lg-6">
<h2>Marketing Quote of the day</h2>
#foreach($quotes->all() as $quote)
<li>{{$quote}}</li>
#endforeach
<br>
</div>
<div class="col-lg-6">
<img src="img/computer.jpg" class="image-fluid" alt="">
</div>
</div>
</div>
Migration Table for Quotes
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateQuotesTable extends Migration
{
public function up()
{
Schema::create('quotes', function (Blueprint $table) {
$table->bigIncrements('id');
$table->text('quote');
$table->string('author');
$table->timestamps();
});
}
public function down()
{
Schema::dropIfExists('quotes');
}
}
Why do I get this error? And how do I get only one quote to display at a time and only change upon each page refresh?
Thank you.
I advise you to input the variable $quotes in the controller, And I remember the passed variable array key which can use and not have to use all function.
The below code from laravel manual:
Route::get('greeting', function () {
return view('welcome', ['name' => 'Samantha']);
});
Hello, {{ $name }}.
change
#foreach($quotes->all() as $quote)
<li>{{$quote}}</li>
#endforeach
into
#foreach($quotes as $quote)
<li>{{$quote}}</li>
#endforeach
TL;DR I want to show submitted posts instantly instead of having to refresh my page
Using the Wordpress REST API I am able to create a new post without any issue. The post is being displayed as soon as the page refreshes, so what I want to do is update the posts object in my Hello.vue file as soon as I create that post so I don't need to refresh to show my newest posts.
I'm not really sure where to start - I've removed all of the experiments I've done so far (importing Post in Create, defining props, pushing to an array, reading about object reactivity on the official Vue documentation, nothing helped).
My App.js consists of the <router> object which shows Hello.vue and a component called Create which displays the Create.vue component. This is how my app currently looks like:
My App.vue file:
<template>
<div id="app">
<section class="posts">
<router-view></router-view>
<create></create>
</section>
</div>
</template>
<script>
import Create from '#/components/Create.vue'
export default {
name: 'app',
components: {
Create
}
}
</script>
<style lang="scss">
#import '../src/assets/styles/style.scss'
</style>
My Hello.vue which displays all the posts:
<template>
<div>
<section class="posts__Feed">
<ul class="posts__List">
<post v-for="item in posts" :item="item" :key="item.id"></post>
</ul>
</section>
</div>
</template>
<script>
var postsUrl = '/wp-json/wp/v2/posts/'
import Post from '#/components/Post.vue'
export default {
name: 'hello',
props: ['responseData'],
components: {
Post
},
data () {
return {
posts: []
}
},
beforeCreate () {
this.$http.get(postsUrl).then((response) => {
this.posts = response.data
})
}
}
</script>
And finally, the Create.vue file which creates the post:
<template>
<div>
<section class="posts__Create">
<form class="posts__CreateForm" v-on:submit="createPosts">
<div class="posts__CreateFormWrapper" v-bind:class="{ 'is-Loading': loading }">
<p>
<input v-model="formInfo.title" type="text" name="title" id="title" placeholder="Name" :disabled="formSent">
</p>
<p>
<textarea v-model="formInfo.content" name="content" id="content" cols="20" rows="10" maxlength="140" placeholder="Message" :disabled="formSent"></textarea>
</p>
<p>
<button :disabled="formSent">Send</button>
</p>
</div>
</form>
</section>
</div>
</template>
<script>
var postsUrl = '/wp-json/wp/v2/posts/'
export default {
name: 'create',
data () {
return {
formInfo: [],
responseData: [],
loading: false,
formSent: false
}
},
methods: {
createPosts (e) {
e.preventDefault()
var info = this.formInfo
// Check if fields are empty
if (this.formInfo.title && this.formInfo.content) {
this.loading = true
// POST
this.$http.post(postsUrl, info).then((response) => {
this.formSent = true
this.loading = false
// get body data
this.responseData = response.data
})
}
} // EOF createPosts
}
}
</script>
Any help would be much appreciated!
I ended up using an event bus as suggested by wotex. First, I've createad a file called bus.js with the below code:
import Vue from 'vue'
export const EventBus = new Vue()
Next, import bus.js to both .vue layouts using:
import { EventBus } from '#/bus.js'
Now emit the event as soon as a new post is created (this is sitting in my axios POST request inside the Create.vue file):
EventBus.$emit('newPost', this.responseData)
And finally, check if the event has happened on the other end (my Hello.vue file):
EventBus.$on('newPost', function (postData) {
Thanks for pointing me in the right direction!
I'm doing project themming WordPress using vue.js and wp rest API. But now I can not render data. Here is my code
app.js
var App = Vue.extend({});
var postList = Vue.extend({
template:'#post-list-template',
data: function(){
return {
posts: ''
}
},
ready: function(){
posts = this.$resource('/wp-json/wp/v2/posts?per_page=20');
posts.get(function(posts){
this.$set('posts', posts);
})
}
})
var router = new VueRouter({
routes: [
{ path: '/', component: postList }
]
})
new Vue({
el: '#app',
router: router,
template: '<router-view></router-view>'
})
**index.php**
<?php get_header(); ?>
<div class="white-wrap">
<div id="app">
<router-view></router-view>
</div>
</div>
<template id="post-list-template">
<div class="container">
<div class="post-list">
<article v-for="post in posts" class="post">
<div class="post-content">
<h2>{{ post.title.rendered }}</h2>
</div>
</article>
</div>
</div>
</template>
<?php get_footer(); ?>
I don't know if I'm doing the right thing, because I am new in vue.js even any languages I'm just a beginner.
Within your data function your returning the posts as an empty string. It should be an empty array.
Right now your trying to use v-for to loop over a string of posts. You should be looping through an array of post objects.
Also, instead of the ready function use an earlier hook like beforeCreate
That should take care of your problem.
I'm using nervgh's angular-file-upload, https://github.com/nervgh/angular-file-upload/wiki/Module-API.
Is there a way to use the angular-file-upload and allow additional properties to each file when doing a multi-file upload?
I'm using their image sample to start out with: http://nervgh.github.io/pages/angular-file-upload/examples/image-preview/
Trying to add a boolean to each file that the user can set and then I use that on the server side when it's picked up.
You can use formData property shown in Properties section to send to server whatever you need.
formData {Array}: Data to be sent along with the files.
If you're using PHP in server side, I think this post can help you out.
The question is rather old, but as the documentation didn't really help me much, I would like to note down my solution here:
This is how my html looks like (look for "options"):
<div ng-controller="UploadCtrl2" nv-file-drop="" uploader="uploader" filters="customFilter">
<div class="progress progress-xs margin-top-5 margin-bottom-20">
<div class="progress-bar" role="progressbar" ng-style="{ 'width': uploader.progress + '%' }"></div>
</div>
<div class="row">
<div class="col-md-6">
<div ng-show="uploader.isHTML5">
<div class="well my-drop-zone" nv-file-drop="" options="{formData:[{folder:'attachments'}, {recordid:0}]}" uploader="uploader">
Dateien hierher ziehen.
</div>
</div>
</div>
<div class="col-md-6">
<span class="btn btn-primary btn-o btn-file margin-bottom-15"> Dateien auswählen
<input type="file" nv-file-select="" options="{formData:[{folder:'attachments'}, {recordid:0}]}" uploader="uploader" multiple />
</span>
</div>
</div>
</div>
And this is my controller (look for "fileItemOptions"):
app.controller('UploadCtrl2', ['$rootScope', '$scope', 'FileUploader', 'Store',
function ($rootScope, $scope, FileUploader, Store) {
var fileItemOptions = {};
var uploader = $scope.uploader = new FileUploader({
url: $rootScope.app.api.url + '/?c=uploads&a=set&authToken=' + encodeURIComponent(Store.get('X-Xsrf-Token')),
});
// FILTERS
uploader.filters.push({
name: 'customFilter',
fn: function (item/*{File|FileLikeObject}*/, options) {
if(options) fileItemOptions = options;
return this.queue.length < 10;
}
});
uploader.removeAfterUpload = true;
// CALLBACKS
uploader.onAfterAddingFile = function (fileItem, options) {
//console.info('onAfterAddingFile', fileItem);
if(fileItemOptions.formData) {
fileItem.formData = fileItemOptions.formData;
}
};
uploader.onAfterAddingAll = function (addedFileItems) {
setTimeout(function () {
console.log(uploader);
uploader.uploadAll();
}, 500);
};
uploader.onCompleteAll = function () {
$scope.$parent.run.uploadComplete();
fileItemOptions = {}; // cleanup
};
}]);
Whenever a file is added, the custom filter stores the option object in a global variable. The callback "onAfterAddingFile" will read that variable and it to the fileItem object. Quite hacky, but this was the only way I got it running.
I am trying to get reactive-tables to work but I am having no luck following the instructions on GitHub.
This is what I have:
In my Main.html:
{{> courseTable }}
in my course_table.html:
<template name="courseTable">
<div id="table">
{{ > reactiveTable collection=Courses}}
</div>
</template>
in courses.js:(works with autoForm)
Courses = new Meteor.Collection("courses", {
schema: {....
Is there something I am missing? From my understanding once these commands are used, the rest is done from within the package. I can't find any more information on this package anywhere.
What I have now just shows a blank screen.
Thanks in advance!
This is what I have: (I'm using Meteor framework and bootstrap-3 package)
in index.html
<template name="clientes">
<div class="container">
<div class="panel panel-primary">
<div class="panel-heading">
<h3 class="panel-title">Clientes</h3>
</div>
<div class="panel-body">
{{> reactiveTable collection=tables settings=tableSettings}}
</div>
</div>
</div>
</template>
in index.js
var Clientes = new Meteor.Collection('clientes')
Template.clientes.tables = function () {
return Clientes;
}
Template.clientes.tableSettings = function () {
return {
rowsPerPage: 10,
showFilter: false,
showNavigation: 'auto',
fields: [
{ key: 'nombre', label: 'Nombre' },
{ key: 'apellido', label: 'Apellido' },
{ key: 'correoe', label: 'E-mail' }
],
useFontAwesome: true,
group: 'client'
};
}
With this I can display all the records in the collection.
I hope this help you to go any further.
Courses is the collection object. To get some courses, you need to query the courses with find:
Courses.find()
However, to make this accessible in the template, you need a helper function.
//course_table.js
Template.courseTable.helpers({
courses: function () {
return Courses.find()
}
});
Then you can can set the table collection using the helper method (I used a lowercase "courses" for the helper method for clarity):
{{> reactiveTable collection=courses}}