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');
}]
};
};
}

Categories