I get stuck on a foreach loop inside my blade template after hours of trial and failure I need some help.
My Controller
public function menue() {
$restaurants = User::with('articles')->get();;
return view('pages.menues')->withRestaurants($restaurants);
}
My foreach
#foreach($restaurants as $restaurant)
<div class="panel panel-default">
<div class="panel-heading">
#foreach($restaurant->articles as $article)
{{$article->title}}
<span class="float-right">{{$article->published_at}}</span>
#endforeach
</div>
<div class="panel-body">
#foreach($restaurant->articles as $article)
{{$article->body}}
#endforeach
{{$restaurant->name}}
</div>
</div>
#endforeach
This is what I'm trying to loop trough:
{
"id":1,
"name":"Sam",
"email":"sam#me.com",
"created_at":"2016-07-26 15:03:51",
"updated_at":"2016-07-27 15:39:55",
"articles":[
{
"id":1,
"user_id":1,
"title":"Monday Afternoon",
"body":"got it",
"created_at":"2016-07-27 15:31:05",
"published_at":"2016-07-27 15:30:00",
"excerpt":null,
"updated_at":"2016-07-27 15:31:05"
},
{
"id":3,
"user_id":1,
"title":"Good Morning Wednesday",
"body":"lorem ipsum",
"created_at":"2016-07-27 11:38:37",
"published_at":"2016-07-27 11:38:00",
"excerpt":null,
"updated_at":"2016-07-27 11:38:37"
},
{
"id":4,
"user_id":1,
"title":"Good Morning Thursday",
"body":"lorem ipsum ",
"created_at":"2016-07-27 11:39:14",
"published_at":"2016-07-28 14:38:00",
"excerpt":null,
"updated_at":"2016-07-27 11:39:14"
},
{
"id":5,
"user_id":1,
"title":"Wednesday Afternoon",
"body":"Hallo Welt",
"created_at":"2016-07-27 14:55:00",
"published_at":"2016-07-27 14:54:00",
"excerpt":null,
"updated_at":"2016-07-27 14:55:00"
}
]
}
Output of my blade template
The result is instead of four posts I get only 2 posts. Each of them contains to other posts. How can I display all 4 posts individually in my view?
Try This
#foreach($restaurants as $restaurant)
#foreach($restaurant->articles as $article)
<div class="panel panel-default">
<div class="panel-heading">
{{$article->title}}
<span class="float-right">{{$article->published_at}}</span>
</div>
<div class="panel-body">{{$article->body}}</div>
</div>
#endforeach
#endforeach
Related
I am beginner webdeveloper. I use in my project Laravel 8 and Vue.
I have this code:
<template>
<div class="sm:bg-transparent pt-6 md:mt-16 w-full px-4 md:px-0">
<h1 class="text-dark text-4xl sm:text-3xl font-medium sm:text-center mb-6">{{ __('Archiwum') }}</h1>
<preloader
v-if="isLoadingInProgress"
class="py-8"
:class="preloaderClass"
/>
<div class="text-center" v-if="gasmeters.length == 0 && !isLoadingInProgress">
{{ __('Nie posiadasz jeszcze żadnych odczytów') }}
</div>
<div v-if="gasmeters.length">
<div class="bg-white rounded border border-stroke flex items-start p-6"
v-for="(gasmeter, index) in gasmeters"
v-bind:key="`gasmeter-${index}`">
<div class="mr-6">
<img class="mb-2" :src="gasmeters.img"/> {{ gasmeters }}
</div>
<div class="w-1/5">
<span class="font-bold text-xl text-grey">Lipiec 2020 (#123)</span>
</div>
<div class="w-1/5">
<span class="font-bold text-xl text-grey">Stan:</span> <span>2120</span>
</div>
<div class="w-1/5">
<span class="font-bold text-xl text-grey">Data:</span> <span>2020.01.12</span>
</div>
<div class="w-1/5">
<span class="text-xl">Zgłoszone przez aplikację</span>
</div>
</div>
</div>
</div>
</template>
<script>
import axios from "axios";
import Preloader from "#/common/components/Preloader";
export default {
components: {
Preloader
},
mounted() {
this.loadGasmeters();
},
data() {
return {
gasmeters: [],
isLoadingInProgress: false,
}
},
computed: {
preloaderClass() {
return this.gasmeters.length > 0
? ""
: "loading--transparent loading--block";
}
},
methods: {
loadGasmeters() {
this.isLoadingInProgress = true;
axios
.get(route('api.archive.list'))
.then(response => {
this.gasmeters = _.get(response, "data.data", []);
console.log(this.gasmeters);
})
.catch(error => {
console.log(error);
})
.then(() => {
this.isLoadingInProgress = false;
});
},
}
}
</script>
My php return me:
{
"data": [
[
{
"id": 1,
"value": "99.00",
"settlement_date": "2020-10-20T22:00:00.000000Z",
"loaded_from": "Stan pobrany z systemu BAŁTYKGAZ",
"img": "img/icons/crm.svg",
"created_at": "2020-10-21T15:09:22.000000Z"
},
{
"id": 2,
"value": "109.00",
"settlement_date": "2020-10-20T22:00:00.000000Z",
"loaded_from": "Zgłoszone przez aplikację",
"img": "img/icons/cms.svg",
"created_at": "2020-10-21T17:02:18.000000Z"
}
]
]
}
I have problem with my part this code:
<div v-if="gasmeters.length">
<div class="bg-white rounded border border-stroke flex items-start p-6"
v-for="(gasmeter, index) in gasmeters"
v-bind:key="`gasmeter-${index}`">
<div class="mr-6">
<img class="mb-2" :src="gasmeters.img"/> {{ gasmeters }}
</div>
<div class="w-1/5">
<span class="font-bold text-xl text-grey">Lipiec 2020 (#123)</span>
</div>
<div class="w-1/5">
<span class="font-bold text-xl text-grey">Stan:</span> <span>2120</span>
</div>
<div class="w-1/5">
<span class="font-bold text-xl text-grey">Data:</span> <span>2020.01.12</span>
</div>
<div class="w-1/5">
<span class="text-xl">Zgłoszone przez aplikację</span>
</div>
</div>
</div>
I want replace my img by img from json, "Lipiec 2020 (#123)" => gasmeters.settlement_date (# gasmeters.id), "Stan: " 2120 => Stan: gasmeters.value
How can I make it?
This: {{ gasmeters }} return me:
[ [ { "id": 1, "value": "99.00", "settlement_date": "2020-10-20T22:00:00.000000Z", "loaded_from": "Stan pobrany z systemu BAŁTYKGAZ", "img": "img/icons/crm.svg", "created_at": "2020-10-21T15:09:22.000000Z" }, { "id": 2, "value": "109.00", "settlement_date": "2020-10-20T22:00:00.000000Z", "loaded_from": "Zgłoszone przez aplikację", "img": "img/icons/cms.svg", "created_at": "2020-10-21T17:02:18.000000Z" } ] ]
Please help me
I saw Your problem. Because your response data from service API Laravel is the array in array. If you want to get your right data, you can do in 2 way:
You change the front end data when get from service API, like this:
axios.get(route('api.archive.list'))
.then(response => {
this.gasmeters = _.get(response, "data.data[0]", []);
console.log(this.gasmeters);
})
.catch(error => {
console.log(error);
})
.then(() => {
this.isLoadingInProgress = false;
});
Or you can change the Laravel API like this:
{
"data": [{
"id": 1,
"value": "99.00",
"settlement_date": "2020-10-20T22:00:00.000000Z",
"loaded_from": "Stan pobrany z systemu BAŁTYKGAZ",
"img": "img/icons/crm.svg",
"created_at": "2020-10-21T15:09:22.000000Z"
},
{
"id": 2,
"value": "109.00",
"settlement_date": "2020-10-20T22:00:00.000000Z",
"loaded_from": "Zgłoszone przez aplikację",
"img": "img/icons/cms.svg",
"created_at": "2020-10-21T17:02:18.000000Z"
}
]
}
I am building a Laravel app and trying to use vue.js (without much success!). I'm not understanding the way components work with ajax data. Almost all examples I've found showing this functionality define the data for the component at the app level, not the component level.
I'm trying to dynamically define my data in the component itself, and always get the error that Property or method tasks is not defined on the instance but referenced during render. Here's the component, which is meant to just call out to an endpoint to pull basic "to do" tasks:
Vue.component('tasks', {
data: function() {
return {
tasks: []
}
},
mounted() {
this.getTasks();
},
methods: {
getTasks() {
axios.get('/tasks').then(function (response) {
this.tasks = response.data;
console.dir(this.tasks);
})
.catch(function (error) {
console.log(error);
});
}
},
template: `
<div class="card">
<div class="card-title">{{ task.name }}</div>
<div class="card-body">
<div class="service-desc">{{ task.description }}</div>
<div class="task-notes"><input class="form-control" v-model="task.notes" placeholder="Notes"></div>
<div class="task-active"><input type="checkbox" checked data-toggle="toggle" data-size="sm" v-model="task.active" v-on:click="$emit('disable')"></div>
</div>
</div>
`
});
the component is called from within the blade template using:
<tasks v-for="task in tasks" :key="task.id"></tasks>
tasks is declared in the data function, so I'm not sure why vue is telling me it's not defined?
When you define a data property on a component it's only available within that component and its template. Your v-for directive is in the parent scope (i.e outside of the component where tasks is defined).
The simplest solution here is probably to move the container element inside the component, and iterate over the tasks there:
<div>
<div class="card" v-for="task in tasks" :key="task.id">
<div class="card-title">{{ task.name }}</div>
<div class="card-body">
<div class="service-desc">{{ task.description }}</div>
<div class="task-notes"><input class="form-control" v-model="task.notes" placeholder="Notes"></div>
<div class="task-active"><input type="checkbox" checked data-toggle="toggle" data-size="sm" v-model="task.active" v-on:click="$emit('disable')"></div>
</div>
</div>
</div>
Note: you can't use v-for a template's root element, which is why you'd move the container element into the template.
An alternative is break this into two components (e.g. TaskList and TaskItem) where the parent component is responsible for fetching the tasks from the API. The child component can just receive a single task as a prop and render it to the UI.
TaskList
Vue.component('task-list', {
data: function() {
return {
tasks: []
}
},
mounted() {
this.getTasks();
},
methods: {
getTasks() {
axios.get('/tasks').then(response => {
this.tasks = response.data;
console.dir(this.tasks);
})
.catch(error => {
console.log(error);
});
}
},
template: `
<div class="container">
<task-item
v-for="task in tasks"
:key="task.id"
:task="task"
/>
</div>
`
});
TaskItem
Vue.component('tasks', {
props: {
task: {
required: true
}
},
template: `
<div class="card">
<div class="card-title">{{ task.name }}</div>
<div class="card-body">
<div class="service-desc">{{ task.description }}</div>
<div class="task-notes"><input class="form-control" v-model="task.notes" placeholder="Notes"></div>
<div class="task-active"><input type="checkbox" checked data-toggle="toggle" data-size="sm" v-model="task.active" v-on:click="$emit('disable')"></div>
</div>
</div>
`
});
The advantage of this is that it separates the responsibility of the components a little better. You could add logic to the TaskList component to handle displaying a loading spinner and/or error messages for the API call, while TaskItem only has to concern itself with displaying a single task.
I'm new to Vue and trying to display data fetched by axios to a modal.
The problem is the modal doesn't display the data.
I've checked the birthday variable and it does contain the data.
Template
<div class="modal fade" tabindex="-1" id="birthdayModal" role="dialog">
<div class="modal-dialog modal-md modal-dialog-centered" role="document">
<div class="modal-content mx-auto text-center bg-danger text-warning">
<div class="modal-body">
<h1>
HAPPY
<i class="fa-fw fas fa-birthday-cake"></i> BIRTHDAY!
</h1>
<img
:src="'/img/members/' +birthday.dob"
width="250px"
height="250px"
class="img img-responsive"
/>
<h3 class="mt-3">{{birthday.alias_name}}</h3>
<h3>{{birthday.dob}}</h3>
</div>
</div>
</div>
</div>
Script
<script>
export default {
data() {
return {
birthday: [],
}
},
methods: {
birthdayModal() {
axios
.get('api/members/birthday')
.then(res => (this.birthday = res.data))
.then($('#birthdayModal').modal('show'))
console.log('Birthday Data: ', this.birthday)
},
},
created() {},
mounted() {
this.birthdayModal()
console.log('Component mounted.')
},
}
</script>
Controller
public function birthday()
{
$date = Carbon::now();
$member = Member::whereMonth('dob', '=', $date->month)->whereDay('dob', '=', $date->day)->get();
return $member;
}
First of all, welcome to StackOverflow HelloWorld1014!
I had a similar problem in my project, where datepicker.js wouldn't load in my modal. I resolved this by re-initializing the datepicker on modal shown event.
I did something like this:
$('#myModal').on('shown.bs.modal', function (e) {
$('.date').datepicker();
});
Hope that this can lead you in right direction.
As #ambianBeing pointed out, you don't need two .then(...). Instead, you should create another method, and call it in your first .then(...).
For example:
export default {
data(){
return{
birthday:[],
}
},
methods:{
birthdayModal(){
axios.get('api/members/birthday').then(res=>this.parseAndDisplay(res));
},
parseAndDisplay(result){
this.birthday = result.data;
$('#birthdayModal').modal('show'));
console.log("Birthday Data: ", this.birthday);
}
},
created(){
},
mounted() {
this.birthdayModal();
console.log('Component mounted.')
}
}
Hope this helps.
I have a page called Home.vue i have a router link which is id once users click it it takes them to the page, how can i display the data elements of the clicked id?
<li class="ta-track-card column col-2 flex-column" v-for="faq in faqs">
<div class="inner">
<div class="artwork" role="link">
<router-link :to="`/album/${faq.id}`"><span :style="`background-image: url('http://localhost/mymusic/${faq.artworkPath}');`"></span></router-link>
</div>
<div class="info">
<div class="title white-primary-hover"><router-link :to="`/album/${faq.id}`">{{ faq.title }}</router-link></div>
<div class="username light-white-hover">
<span>by </span>
<router-link :to="`/artist/${faq.artistId}`">{{ faq.artist }}</router-link>
</div>
<div class='released'>Released On {{ faq.albumdate }}</div>
</div>
</div>
</li>
Below is the Album.vue Page where i display the data
<div class="entityInfo">
<div class="leftSection" v-for="faq in faqs">
<img :src="/""faq.artworkPath">
</div>
<div class="rightSection" v-for="faq in faqs" :key="faq.id">
<h2 class="_good">{{ faq.title }}</h2>
<p class="_me">By {{ faq.artist }}</p>
<p class="_me">1 songs</p>
<p class="_me">{{ faq.albumdate }}</p>
</div>
Below is Script i use:
<script>
import axios from 'axios';
export default {
name: 'album',
data: () =>({
faqs: [],
songs: [],
errors: []
}),
created() {
axios.get('http://localhost/mymusic/rest/api/album/read')
.then(response => {
this.faqs = response.data.data;
})
.catch(e => {
console.log(e),
this.errors.push(e)
})
}
}
</script>
Below is the Sample API:
{
"data": [
{
"id": "41",
"artistId": "38",
"title": "Red Handed",
"artist": "Peruzzi & Mayorkun",
"artworkPath": "assets/images/artwork/red.jpg",
"albumdate": "2018-09-24"
},
{
"id": "40",
"artistId": "37",
"title": "FEFE (feat. Nicki Minaj & Murda Beatz)",
"artist": "6ix9ine",
"artworkPath": "assets/images/artwork/fefe.jpg",
"albumdate": "2018-07-22"
},
}
Please how can i display the element of the Id i click from the router
As i can see you are passing the id in the route you can retrieve it using id = this.$route.params.id and store it in a temporary variable.And in created just retrieve the data by passing id in post parameter and changing your query accordingly.Or the other option is to loop over through your retrieved data and filter them from the selected id.
Or rather then filter create the data object as id->value pairs to directly access them through id and you will have to make single api call.
In my project I often need to reuse the same template on different pages usually with the different filter parameters. I considered to use controller methods and the twig render function to carry it out.
In my controller:
public function index(Request $request) {
return $this->render("index.html.twig");
}
public function list(Request $request, array $filterArray = []) {
return $this->render("list.html.twig", [
'items' => $this->getFilteredItems($filterArray)
]);
}
public function entry(Request $request, string $alias) {
return $this->render("entry.html.twig"[
'item' => $this->getItemByAlias($alias)
]);
}
In index.html.twig:
{{ render(controller(
'App\\Controller\\SynthesisController::entityList', {},
{ }
)) }}
In list.html.twig:
{% for item in items %}
<div class="">
{{item.name}}
</div>
{% endfor %}
And so it allows me to reuse the list of entities in other pages with its layout. In entry.html.twig:
<div class="synthesis-participants">
<div class="row">
<div class="col-sm-6 mb-4">
<div class="h5">Reagents:</div>
{{ render(controller(
'App\\Controller\\SubstanceController::entityList', { 'filterArray': {
'participate': { 'synthesis': item.id, 'role': 10 }
} }, { }
)) }}
</div>
<div class="col-sm-6 mb-4">
<div class="h5">Products:</div>
{{ render(controller(
'App\\Controller\\SubstanceController::entityList', { 'filterArray': {
'participate': { 'synthesis': item.id, 'role': 20 }
} }, { }
)) }}
</div>
</div>
<div class="row">
<div class="col-sm-6 mb-4">
<div class="h5">Diluents:</div>
{{ render(controller(
'App\\Controller\\SubstanceController::entityList', { 'filterArray': {
'participate': { 'synthesis': item.id, 'role': 30 }
} }, { }
)) }}
</div>
<div class="col-sm-6 mb-4">
<div class="h5">Catalysts:</div>
{{ render(controller(
'App\\Controller\\SubstanceController::entityList', { 'filterArray': {
'participate': { 'synthesis': item.id, 'role': 40 }
} }, { }
)) }}
</div>
</div>
<p class="mt-2">{{ item.text }}</p>
</div>
May be it can be reached in a better way?
In my opinion you should avoid this way since you are embedding too many controllers and I find the overhead bigger than the benefit.
Alternatively you could add some functionality in each of your controllers to get the necessary information and then include the appropriate templates in your twig.
I would change your controllers to something like this:
public function index(Request $request) {
return $this->render("index.html.twig", [
'items' => $this->getFilteredItems()
]);
}
public function list(Request $request, array $filterArray = []) {
return $this->render("list.html.twig", [
'items' => $this->getFilteredItems($filterArray)
]);
}
public function entry(Request $request, string $alias) {
$item = $this->getItemByAlias($alias);
$items = [];
$titles = ['Reagents', 'Products', 'Diluents', 'Catalysts'];
foreach (range(10, 40, 10) as $key => $role) {
$filter['participate'] = [
'synthesis' => $item['id'], // $item->getId()
'role' => $role
];
$title = $titles[$key];
$items[$title] = $this->getFilteredItems($filter);
}
return $this->render("entry.html.twig"[
'item' => $this->getItemByAlias($alias),
'items' => $items
]);
}
Finally, in your entry.html.twig:
<div class="synthesis-participants">
{% for key, itemArray in items %}
<div class="row">
<div class="col-sm-6 mb-4">
<div class="h5">{{ key }} :</div>
{% include 'list.html.twig' with {'items': itemArray} only %}
</div>
</div>
{% endfor %}
<p class="mt-2">{{ item.text }}</p>
</div>
I would also suggest that the functions getItemByAlias, getFilteredItems shouldn't live in the controller but in a repository or service.