FullCalendar - I can't retrieve the events on the calendar - javascript
I have json format events available on a "/ index" url. I would like to be able to retrieve them in order to display them on the calendar. I followed the official tutorial to the letter but unfortunately I still can't do it, here are my files:
calendar.js
$(function () {
'use strict'
// Initialize fullCalendar
$('#calendar').fullCalendar({
height: 'parent',
locale: 'fr',
header: {
left: 'prev,next today',
center: 'title',
right: 'month,agendaWeek,agendaDay,listWeek'
},
navLinks: true,
selectable: true,
selectLongPressDelay: 100,
editable: true,
nowIndicator: true,
defaultView: 'listMonth',
views: {
agenda: {
columnHeaderHtml: function (mom) {
return '<span>' + mom.format('ddd') + '</span>' +
'<span>' + mom.format('DD') + '</span>';
}
},
day: {
columnHeader: false
},
listMonth: {
listDayFormat: 'ddd DD',
listDayAltFormat: false
},
listWeek: {
listDayFormat: 'ddd DD',
listDayAltFormat: false
},
agendaThreeDay: {
type: 'agenda',
duration: {
days: 3
},
titleFormat: 'MMMM YYYY'
}
},
events: "/index",
eventAfterAllRender: function (view) {
if (view.name === 'listMonth' || view.name === 'listWeek') {
var dates = view.el.find('.fc-list-heading-main');
dates.each(function () {
var text = $(this).text().split(' ');
var now = moment().format('DD');
$(this).html(text[0] + '<span>' + text[1] + '</span>');
if (now === text[1]) {
$(this).addClass('now');
}
});
}
console.log(view.el);
},
eventRender: function (event, element) {
if (event.description) {
element.find('.fc-list-item-title').append('<span class="fc-desc">' + event.description + '</span>');
element.find('.fc-content').append('<span class="fc-desc">' + event.description + '</span>');
}
var eBorderColor = (event.source.borderColor) ? event.source.borderColor : event.borderColor;
element.find('.fc-list-item-time').css({
color: eBorderColor,
borderColor: eBorderColor
});
element.find('.fc-list-item-title').css({
borderColor: eBorderColor
});
element.css('borderLeftColor', eBorderColor);
},
});
var calendar = $('#calendar').fullCalendar('getCalendar');
// change view to week when in tablet
if (window.matchMedia('(min-width: 576px)').matches) {
calendar.changeView('agendaWeek');
}
// change view to month when in desktop
if (window.matchMedia('(min-width: 992px)').matches) {
calendar.changeView('month');
}
// change view based in viewport width when resize is detected
calendar.option('windowResize', function (view) {
if (view.name === 'listWeek') {
if (window.matchMedia('(min-width: 992px)').matches) {
calendar.changeView('month');
} else {
calendar.changeView('listWeek');
}
}
});
// Display calendar event modal
calendar.on('eventClick', function (calEvent, jsEvent, view) {
var modal = $('#modalCalendarEvent');
modal.modal('show');
modal.find('.event-title').text(calEvent.title);
if (calEvent.description) {
modal.find('.event-desc').text(calEvent.description);
modal.find('.event-desc').prev().removeClass('d-none');
} else {
modal.find('.event-desc').text('');
modal.find('.event-desc').prev().addClass('d-none');
}
modal.find('.event-start-date').text(moment(calEvent.start).format('LLL'));
modal.find('.event-end-date').text(moment(calEvent.end).format('LLL'));
//styling
modal.find('.modal-header').css('backgroundColor', (calEvent.source.borderColor) ? calEvent.source.borderColor : calEvent.borderColor);
});
//display current date
var dateNow = calendar.getDate();
calendar.option('select', function (startDate, endDate) {
$('#modalCreateEvent').modal('show');
$('#eventStartDate').val(startDate.format('LL'));
$('#eventEndDate').val(endDate.format('LL'));
$('#eventStartTime').val('07:00:00').trigger('change');
$('#eventEndTime').val('10:00:00').trigger('change');
});
$('.select2-modal').select2({
minimumResultsForSearch: Infinity,
dropdownCssClass: 'select2-dropdown-modal',
});
$('.calendar-add').on('click', function (e) {
e.preventDefault()
$('#modalCreateEvent').modal('show');
});
})
web.php (laravel)
<?php
use Illuminate\Support\Facades\Route;
/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| contains the "web" middleware group. Now create something great!
|
*/
/* Courses Routes */
Route::post('admin/calendar', 'CoursesController#store')->name('courses.store');
Route::get('index', 'CoursesController#index');
Result when I do a request on "/ index", this is the result:
{
"backgroundColor": "rgba(91,71,251,.2)",
"borderColor": "#5b47fb",
"events": [{
"start": "2020-10-07T07:00:00",
"end": "2020-10-07T10:00:00",
"title": "statistiques",
"description": "drink Coffee"
}]
};
Screenshot of similar result:
Here is the class "Coursescontroller" which manages everything
<?php
namespace App\Http\Controllers;
use App\Courses;
use Illuminate\Support\Str;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Auth;
use App\Http\Resources\CourseResource;
class CoursesController extends Controller
{
/**
* Create a new controller instance.
*
* #return void
*/
public function __construct()
{
$this->middleware('auth:admin');
}
/**
* retrieve the data from the "courses" table
*
* #return \Illuminate\Http\Response
*/
public function index()
{
$course = DB::select('select * from courses where universityReference = ?', [Auth::user()->universityReference]);
//let's select the first line
$data = [
"backgroundColor" => $course[0]->backgroundColor,
"borderColor" => $course[0]->borderColor,
"events" => [unserialize($course[0]->events)]
];
return array($data);
}
/**
* Show the form for creating a new resource.
*
* #return \Illuminate\Http\Response
*/
public function create()
{
//
}
/**
* transform the raw data collected, in order to properly format them for recording
*
*/
public function composeCourseData($arg)
{
//convert dates into ISODATE format ('Y-m-d')
$convertStartDate = date('Y-m-d', strtotime(str_replace('-', '/', $arg->input('startDate'))));
$convertEndDate = date('Y-m-d', strtotime(str_replace('-', '/', $arg->input('endDate'))));
//convert times into ISOTIME format (H:M:S)
$convertStartTime = strftime('%H:%M:%S', strtotime($arg->input('startTime')));
$convertEndTime = strftime('%H:%M:%S', strtotime($arg->input('endTime')));
//final datetime output
$outputStartDate = "".$convertStartDate."T".$convertStartTime."" ;
$outputEndDate = "".$convertEndDate."T".$convertEndTime."" ;
//array to store course basic informations
$courseData = array(
'courseToken' => Str::random(23,'alphaNum'),
'creatorReference' => Auth::user()->reference,
'professorName' => $arg->input('professorName'),
'location' => $arg->input('location'),
'start' => $outputStartDate,
'end' => $outputEndDate,
'title' => $arg->input('subject'),
'description' => "".$arg->input('type')." '".$arg->input('subject')."' en ".$arg->input('location')." du ".$arg->input('professorName')." avec les etudiants de ".$arg->input('studyYear')." annee (".$arg->input('faculty').")",
);
//serialize course data before saving in db;
return serialize($courseData);
}
/**
* Store a newly created resource in storage.
*
* #param \Illuminate\Http\Request $request
* #return \Illuminate\Http\Response
*/
public function store(Request $request)
{
//Validate informations
/*$course = request()->validate([
/*'professorName'=>'required|string'
'subject'=> 'string|required',
'location'=>'required',
'start'=>'required',
'end'=>'required',
'description'=>'string'
]);*/
/* switch to determine the type of event (course, homework, tutorials or exams)
* in order to assign a color
* */
switch ($request->input('type')) {
case 'examens':
$ok = Courses::create([
//think about how to externalize this part of the code which is repeated almost 4 times
'universityReference' => Auth::user()->universityReference,
'creatorReference' => Auth::user()->reference,
'type' => $arg->input('type'),
'faculty' => $arg->input('faculty'),
'studyYear' => $arg->input('studyYear'),
//green
'backgroundColor' => 'rgba(16,183,89,.25)',
'borderColor' => '#10b759',
'events' => $this->composeCourseData($request)
]);
break;
case 'TD':
Courses::create([
//orange
'universityReference' => Auth::user()->universityReference,
'creatorReference' => Auth::user()->reference,
'type' => $request->input('type'),
'faculty' => $request->input('faculty'),
'studyYear' => $request->input('studyYear'),
'backgroundColor' => 'rgba(253,126,20,.25)',
'borderColor' => '#fd7e14',
'events' => $this->composeCourseData($request)
]);
break;
case 'devoirs':
Courses::create([
//pink
'universityReference' => Auth::user()->universityReference,
'creatorReference' => Auth::user()->reference,
'type' => $request->input('type'),
'faculty' => $request->input('faculty'),
'studyYear' => $request->input('studyYear'),
'backgroundColor' => 'rgba(241,0,117,.25)',
'borderColor' => '#f10075',
'events' => $this->composeCourseData($request)
]);
break;
default:
Courses::create([
//purple
'universityReference' => Auth::user()->universityReference,
'creatorReference' => Auth::user()->reference,
'type' => $request->input('type'),
'faculty' => $request->input('faculty'),
'studyYear' => $request->input('studyYear'),
'backgroundColor' => 'rgba(91,71,251,.2)',
'borderColor' => '#5b47fb',
'events' => $this->composeCourseData($request)
]);
break;
}
return redirect()->route('admin.app.calendar');
}
/**
* Display the specified resource.
*
* #param int $id
* #return \Illuminate\Http\Response
*/
public function show($id)
{
//
}
/**
* Show the form for editing the specified resource.
*
* #param int $id
* #return \Illuminate\Http\Response
*/
public function edit($id)
{
//
}
/**
* Update the specified resource in storage.
*
* #param \Illuminate\Http\Request $request
* #param int $id
* #return \Illuminate\Http\Response
*/
public function update(Request $request, Courses $course)
{
}
/**
* Remove the specified resource from storage.
*
* #param int $id
* #return \Illuminate\Http\Response
*/
public function destroy(Courses $course)
{
$course->delete();
return response('Course removed successfuly !', Response::HTTP_NO_CONTENT);
}
}
I know this is not the satandard use but, i would like to retrieve events in this format, is that possible?
because: I save all the events of the same type ($ request-> input ('type') as (exams or TD ..), in a single "events" array that I store with a precise backgroundColor and borderColor. Every time an event of this same "type" tries to be saved, I just modify the corresponding line by editing the "events" array.
{
backgroundColor: 'rgba(253,126,20,.25)',
borderColor: '#fd7e14',
events: [{
id: '16',
start: '2020-10-07T07:00:00',
end: '2020-10-07T07:00:00',
title: 'My Rest Day'
},
{
id: '17',
start: '2020-10-07T07:00:00',
end: '2020-10-08T11:00:00',
title: 'My Rest Day'
}
]
}
The structure of the JSON being generated by your PHP code not compatible with fullCalendar. It must be a plain array of events, with no outer structure around it.
e.g. it should output this kind of structure
[
{
"start": "2020-10-07T07:00:00",
"end": "2020-10-07T10:00:00",
"title": "statistiques",
"description": "drink Coffee"
}
]
only.
To do that you need to amend your PHP as follows. I've included the background and border colours still, but they need to be appended to each event object individually:
public function index()
{
$course = DB::select('select * from courses where universityReference = ?', [Auth::user()->universityReference]);
//let's select the first line
$data = [unserialize($course[0]->events)];
foreach ($data as $item)
{
$item["backgroundColor"] = $course[0]->backgroundColor;
$item["borderColor"] = $course[0]->borderColor;
}
return $data;
}
Related
Adonisjs How to cast boolean to false and true in a model instead of 0 or 1?
This is my table field (open) but in response, it returns 0 1 but I want true false instead of 0 1 I am using adonis MySQL table.boolean('open').notNullable().defaultTo(true).comment('true = open, false = close') const Model = use('Model') class Markup extends Model { static boot() { super.boot() this.addTrait('#provider:Lucid/SoftDeletes') } static getColumns() { return ['assignee_id', 'editor_details', 'visibility', 'image_url', 'priority', 'open'] } comments() { return this.hasMany('App/Models/Comment', 'id', 'markup_id') } assignee() { return this.belongsTo("App/Models/User", "assignee_id", "id") } created_by() { return this.belongsTo("App/Models/User", 'created_by_id', 'id') } resolved_by() { return this.belongsTo("App/Models/User", 'resolved_by_id', 'id') } } module.exports = Markup
This just a simple fix. you just have to do this in your column. #column({ serialize: Boolean })
As #asad-jivani said: Boolean isn't a distinct datatype in MySQL; it's just a synonym for tinyint. what you can do is write an after hook in your model to convert 1/0 to true/false. In these cases I use a property of laravel/lumen calls $casts, this is specified in the model. here is an example without the $cast to is_draft field. JSON Response: { "areas": [ { "id": 1, "is_draft": 1, "title": "Example" } ] } to convert the filed is_draft to true or false I just added this in my model. <?php namespace App\Models; use Illuminate\Database\Eloquent\Model; class Area extends Model { /** * The attributes that are mass assignable. * * #var array */ protected $table = 'areas'; protected $guarded = []; /** * The attributes excluded from the model's JSON form. * * #var array */ protected $casts = [ 'is_draft' => 'boolean', ]; } and here is the parsed JSON Response: { "areas": [ { "id": 1, "is_draft": true, "title": "Example" } ] } I hope this helps you 👍
Javascript TypeError $(...).functionName is not a function
I'm using the following Javascript to get data via PHP (upload.php) - <script src="js/jquery.amsify.suggestags.js"></script> <script> fetch('./get_hashtags.php').then(response => { return response.json(); }).then(data => { var suggestionsArr = []; data.forEach(function(item){ suggestionsArr.push(item.category); }); console.log(suggestionsArr); $('#inputTags').amsifySuggestags({ suggestions: suggestionsArr, classes: ['bg-warning','bg-warning'], }); }).catch(err => { console.log(err); }); </script> get_hashtags.php <?php // ... some additional database connection details ... $statement = $pdo->prepare("SELECT category FROM hashtags where active=1"); $hashtags = array(); if ($statement->execute()) { while ($row = $statement->fetch(PDO::FETCH_ASSOC)) { $hashtags[] = $row; } } $pdo = null; echo json_encode($hashtags); ?> Unfortunately I'm getting the following error when loading the page - TypeError: $(...).amsifySuggestags is not a function at fetch.then.then.data (upload.php:1550) This is the beginning of jquery.amsify.suggestags.js (https://github.com/amsify42/jquery.amsify.suggestags) - (function($) { $.fn.amsifySuggestags = function(options, method) { /** * Merging default settings with custom * #type {object} */ var settings = $.extend({ type : 'bootstrap', tagLimit : 5, suggestions : [], classes : [], backgrounds : [], colors : [], whiteList : false, afterAdd : {}, afterRemove : {}, }, options); /** * Initialization begins from here * #type {Object} */ var AmsifySuggestags = function() { this.selector = null; this.name = null; ... I don't get the error message when inserting the $('#inputTags').amsifySuggestags outside of the fetch method with some hardcoded values. Thanks in advance!
Symfony access prototype data in a Collection
I am stuck with an issue I cant seem to fix yet , I am trying to edit some bidirectional Many->Many relations in a form using a Collection . It seems that none of my prototype entries are saved upon submitting , and only changes done on initial relations would be taken into account . Here is some of my code : public function buildForm(FormBuilderInterface $builder, array $options) { $item = $builder->getData(); $builder ->add('serviceCol', CollectionType::class, array( 'entry_type' => ServiceType::class, 'entry_options' => array('label' => false,), 'property_path' => 'service', 'allow_add' => true, 'allow_delete' => true, 'by_reference' => false, 'delete_empty' => true, 'prototype' => true, 'mapped' => false, 'data' => $item->getService())) ; } subform : public function buildForm(FormBuilderInterface $builder, array $options) { $builder->addEventListener(FormEvents::PRE_SET_DATA, function (FormEvent $event) use ($builder) { $form = $event->getForm(); $service = $event->getData(); $form->add('service', EntityType::class, array( 'class' => Service::class, 'query_builder' => function (EntityRepository $er) { return $er->createQueryBuilder('s') ->orderBy('s.id_service', 'ASC'); }, 'choice_label' => 'nom', 'property_path' => 'nom', 'mapped' => false, 'label' => false, 'data' => $service, 'placeholder' => 'Aucun')); }); } entity - mappedBy : /** * #ORM\ManyToMany(targetEntity="App\Entity\Service", mappedBy="applis") */ private $services; public function __construct() { $this->services = new ArrayCollection(); } public function addService( Service $service = null ): bool { if ($this->services->contains($service)) { return false; } $this->services[] = $service; return true; } public function remService( Service $service): bool { return $this->services->removeElement($service); } public function getService() { return $this->services; } entity - possessing : /** * #ORM\ManyToMany(targetEntity="App\Entity\Appli", inversedBy="services" ) * #ORM\JoinTable(name="service_to_app", * joinColumns={#ORM\JoinColumn(name="services", referencedColumnName="id_service")}, * inverseJoinColumns={#ORM\JoinColumn(name="applis", referencedColumnName="id_apps")} * ) */ private $applis; public function __construct() { $this->applis = new ArrayCollection(); } public function addApp( Appli $app): bool { //$app->addService($this); if ($this->applis->contains($app)) { return false; } $this->applis[] = $app; return true; } public function remApp( Appli $app){ if ($app->remService($this)){ return $this->applis->removeElement($app); } return false; } public function getApp(){ return $this->applis; } dump($form->all()) doesnt even show anything about my prototypes .. is there something I can do to retrieve those informations before they disappear , in POST_SUBMIT event or anything ? Edit: Javascript : $(document).ready(function() { // On récupère la balise <div> en question qui contient l'attribut « data-prototype » qui nous intéresse. var $container = $('div#appli_form_serviceCol'); // On définit un compteur unique pour nommer les champs qu'on va ajouter dynamiquement var index = $container.find(':input').length; var $button = $('#add_field'); $button.click(function(e) { addField($container); //test(); e.preventDefault(); return false; }); if (index == 0) { addService($container); } else { $container.children('div').each(function() { addDeleteLink($(this)); }); } function addField($container) { var template = $container.attr('data-prototype') .replace(/__name__label__/g, 'service n°' + (index+1)) .replace(/__name__/g, index) ; var $prototype = $(template); addDeleteLink($prototype); $container.append($prototype); index++; console.debug( $prototype); } function addDeleteLink($prototype) { var $deleteLink = $('<button class="delButton">Supprimer</button>'); $prototype.append($deleteLink); $deleteLink.click(function(e) { $prototype.remove(); e.preventDefault(); return false; }); } }); Let me know If there is any relevant code parts I did forget .
Sending array attribute of object to Ajax
(sorry for my english) I have a little problem. Shop Bascket I want to store at session a shop-bascket, so I created the php/classes/bascket.php: class Product { private $id; private $quantity; function __construct(int $id, int $q) { $this->id = $id; $this->quantity = $q; } ... } class Bascket { private $products = array(); /* for testing */ function __construct() { $this->products[] = new Product(26, 1006); } function add(int $id, int $quantity) { ... } function delete(int $id, int $quantity) { ... } function __get($field) { return $this->$field; } } Using the Shop Bascket And I use this class on session anywhere I want: include "php/classes/bascket.php"; (*or another correct path*) session_start(); if(!isset($_SESSION["bascket"])) { $_SESSION["bascket"] = serialize(new Bascket()); } $bascket = unserialize($_SESSION["bascket"]); Trying to display Bascket Shop with Ajax Because I want to show the bascket on pressing a button, I made an ajax which do the following thing: function display_bascket() { $.ajax({ url: 'php/take_bascket.php', dataType: 'text', cache: false, contentType: false, processData: false, type: 'post', success: function(bascket){ //bascket = JSON.parse(bascket); //bascket = jQuery.parseJSON(bascket); $("#content").html(bascket); } }); } And I tried a lot to can display the correct thing in take_bascket.php to receive a good array, or a json in ajax. take_bascket.php <?php session_start(); include "classes/bascket.php"; if(!isset($_SESSION["bascket"])) { $_SESSION["bascket"] = serialize(new Bascket()); } // I tried many variants: var_dump($_SESSION["bascket"]); /* * output: * string(116) "O:3:"Bascket":1:{s:12:"Bascketproducts";a:1:{i:0;O:6:"Product":2:{s:10:"Productid";i:26;s:17:"Productquantity";i:1006;}}}" * * and I don't know how to handled it in ajax to get the products array */ var_dump(unserialize($_SESSION["bascket"])); /* * output: * object(Bascket)#1 (1) { ["products":"Bascket":private]=> array(1) { [0]=> object(Product)#2 (2) { ["id":"Product":private]=> int(26) ["quantity":"Product":private]=> int(1006) } } } * * and I don't know how to handled it in ajax to get the products array */ var_dump(json_encode($_SESSION["bascket"])); /* * output: * string(158) ""O:3:\"Cos\":1:{s:12:\"\u0000Cos\u0000products\";a:1:{i:0;O:6:\"Product\":2:{s:10:\"\u0000Product\u0000id\";i:26;s:17:\"\u0000Product\u0000quantity\";i:1006;}}}"" * * and I don't know how to handled it in ajax to get the products array */ var_dump(((unserialize($_SESSION["bascket"]))->products)); /* * output: * array(1) { [0]=> object(Product)#2 (2) { ["id":"Product":private]=> int(26) ["quantity":"Product":private]=> int(1006) } } * * and I don't know how to handled it in ajax to get the products array */ var_dump(((unserialize($_SESSION["bascket"]))->products[0])); /* * output: * object(Product)#2 (2) { ["id":"Product":private]=> int(26) ["quantity":"Product":private]=> int(1006) } * * and I don't know how to handled it in ajax to get the products array */ Conclusion As you can see I also tried different ways of manipulate the output in ajax. But or it is a string and I can't convert it in array. Or I can't make it json, etc. Please Please, can you try find a complete solution? I mean for take_bascket.php, but also for what I have to do in display_bascket() in js. thank you in advance Edit: I did as someone said in a post: php/classes/bascket.php <?php class Product { private $id; private $quantity; function __construct(int $id, int $q) { $this->id = $id; $this->quantity = $q; } function decrease(int $value) { ... } function increase(int $value) { ... } public function toArray(){ return [ 'id' => $this->id, 'quantity' => $this->quantity, ]; } } class Bascket { private $products = array(); /* for testing */ function __construct() { $this->products[] = new Product(26, 1006); } function add(int $id, int $quantity) { ... } function delete(int $id, int $quantity) { ... } public function toJson(){ $products = []; foreach ($this->products as $product) { $products[] = $product->toArray(); } return json_encode( [ 'products' => $products ], JSON_PRETTY_PRINT ); } function __get($field) { return $this->$field; } } And that's how I would theoretical create a PHP JSON easier. But look at take_bascket.php: <?php session_start(); include "classes/bascket.php"; if(!isset($_SESSION["bascket"])) { $_SESSION["bascket"] = serialize(new Bascket()); } var_dump(((unserialize($_SESSION["bascket"]))->toJson())); /* * output: * string(98) "{ "products": [ { "id": 26, "quantity": 1006 } ] }" */ Trying to use it in display_bascket(): function display_bascket() { $.ajax({ url: 'php/take_bascket.php', dataType: 'text', cache: false, contentType: false, processData: false, type: 'post', success: function(bascket){ //bascket = JSON.parse(bascket); $("#content").html(bascket); } }); } If I don't use JSON.parse(), it'll display the next plain text: string(98) "{ "products": [ { "id": 26, "quantity": 1006 } ] }" Instead, if I use JSON.parse(), I have a console error: Uncaught SyntaxError: Unexpected token s in JSON at position 0 at JSON.parse (<anonymous>)at Object.success (display_bascket.js:10) at j (jquery.js:2) at Object.fireWith [as resolveWith] (jquery.js:2) at x (jquery.js:4) at XMLHttpRequest.b (jquery.js:4) What should I do?
I suggest that in each object you create a method that will return a JSON representation of that object. For instance (filename: products.php): class Product { private $name; private $value; private $quantity; public function __construct($name, $value, $quantity){ $this->name = $name; $this->value = $value; $this->quantity = $quantity; } public function toArray(){ return [ 'name' => $this->name, 'value' => $this->value, 'quantity' => $this->quantity, ]; } } class Basket{ private $products = []; public function addProduct(Product $p){ $this->products[] = $p; } public function toJson(){ $products = []; foreach ($this->products as $p) { $products[] = $p->toArray(); } return json_encode( [ 'products' => $products ], JSON_PRETTY_PRINT ); } } $b = new Basket(); $b->addProduct(new Product('Apple', 1, 5)); $b->addProduct(new Product('Banana', .5, 2)); $b->addProduct(new Product('Carrots', .35, 6)); echo $b->toJson(); This will generate a JSON object that you can use with jQuery .getJSON() method. Like the example below (filename: products.html): <html> <head> <script src="https://code.jquery.com/jquery-3.2.1.min.js"> </script> </head> <body> <h3>Product list</h3> </body> <script> $(function(){ $.getJSON( "products.php", function( data ) { console.log(data); var items = []; $.each( data.products, function( key, val ) { items.push( "<li>Name: " + val.name + " | Quantity: " + val.quantity + " | Price: " + val.value + "</li>" ); }); $( "<ul/>", { html: items.join( "" ) }).appendTo( "body" ); }); }); </script> </html>
Manage subscriptions in ui routes with angular meteor
I'm currently building an application with meteor and angularJS using angular-meteor. I'm currently asking myself, how to properly handle subscriptions. My current approach is to: resolve a route when each dependent subscription is ready make sure that previous subscriptions on that publication are stopped Is there a more performant way of doing this? profileRoutes.js: function profileRoutes($stateProvider, ResolverProvider) { $stateProvider .state('user.profile', { url: '/:username/profile', resolve: _.extend( { $title: ['$stateParams', function($sp) { return $sp.username + "'s Profil"; }] }, ResolverProvider.waitForMedia(), ResolverProvider.waitForUsers() ), abstract: true, views: { 'main': { controller: 'UserProfileController', templateUrl: 'client/components/users/profile.html' } } }); } angular .module('myApp') .config(profileRoutes); resolver.js function ResolverProvider() { /** * _stopIfSubscribed * * Checks if a subscription for that publication is already present and stops it. * #param publicationName * #private */ function _stopIfSubscribed(publicationName) { _.forEach(_.get(Meteor, 'default_connection._subscriptions'), (handle) => { if(_.get(handle, 'name') === publicationName && handle.stop) { handle.stop(); } }); } /** * waitForUsers * * Returns resolvers for waiting on my own and all other users * Does not require a user * #returns {{meSubscription: *[], usersSubscription: *[]}} */ this.waitForUsers = () => { return { "meSubscription": ['$meteor', function ($meteor) { return $meteor.waitForUser(); }], "usersSubscription": ['$meteor', function ($meteor) { _stopIfSubscribed('allUsers'); return $meteor.subscribe('allUsers'); }] }; }; /** * waitForMedia * * Returns resolvers for waiting on galleries and media * #returns {{mediaSubscription: *[], gallerySubscription: *[]}} */ this.waitForMedia = () => { return { "mediaSubscription": ['$meteor', function ($meteor) { _stopIfSubscribed('media'); return $meteor.subscribe('media'); }], "gallerySubscription": ['$meteor', function ($meteor) { _stopIfSubscribed('galleries'); return $meteor.subscribe('galleries'); }] }; }; }