Passing a model from PHP/Laravel to ReactJS Fluxible store - javascript

In my TaskController.php I have:
namespace Api;
use Repos\EnquiryRepo;
class TaskController extends \BaseController {
protected $repo;
function __construct() {
parent::__construct();
$this->repo = new EnquiryRepo();
}
public function show($enquiryId)
{
if(!$enquiry = $this->repo->findById($enquiryId)) {
return $this->json('That does not exist.', 404);
}
return \View::make('task.index', ['enquiry' => $enquiry]);
}
}
I am totally lost as to how I can pass the $enquiry model into my react store:
EnquiryStore.js
import { EventEmitter } from 'events';
export default class EnquiryStore extends EventEmitter {
constructor() {
super();
this.enquiries = new Map();
this.loading = false;
}
handleEnquiriesData(payload) {
payload.data.enquiries.forEach((enquiry) => {
this.enquiries.set(enquiry.id, enquiry);
});
this.loading = false;
this.emit('change');
}
handleReceiving() {
this.loading = true;
this.emit('loading');
}
getEnquiries() {
return this.enquiries;
}
dehydrate () {
return this.enquiries;
}
rehydrate (state) {
}
}
EnquiryStore.handlers = {
'RECEIVED_ENQUIRIES_DATA': 'handleEnquiriesData',
'RECEIVING_ENQUIRIES_DATA': 'handleReceiving'
};
EnquiryStore.storeName = 'EnquiryStore';
Would I need to somehow echo it out into a JS variable or something? How can I get this to work? The whole point is so that when the page loads I have all the data already and React/Fluxible doesn't need to make another request for the data.

After a bit of trail and error I got it working:
In my Laravel view I did:
#extends('layouts.react')
#section('css')
{{HTML::style('/css/task.css?bust=' . time())}}
#stop
#section('js')
<script>
app_dehydrated.context.dispatcher.stores.EnquiryStore = {{$enquiry}}
</script>
#stop
Then my store:
import { EventEmitter } from 'events';
export default class EnquiryStore extends EventEmitter {
constructor() {
super();
this.enquiry = {};
this.loading = false;
}
handleReceiving() {
this.loading = true;
this.emit('loading');
}
getEnquiry() {
return this.enquiry;
}
dehydrate () {
return this.enquiry;
}
rehydrate (state) {
this.enquiry = state;
}
}
EnquiryStore.handlers = {
'RECEIVED_ENQUIRIES_DATA': 'handleEnquiriesData',
'RECEIVING_ENQUIRIES_DATA': 'handleReceiving'
};
EnquiryStore.storeName = 'EnquiryStore';
If there is a better way please tell me! Hope this helps others.

Related

Unable to pass data between two components using services

I want to pass the array value from Search component to History component to display the history of the searches done.
I have written the code in this manner -
search-page.component.ts
export class SearchPageComponent implements OnInit {
constructor( private dataService :DataService) { }
githubSearch(username:any){
return new Promise((resolve, reject) => {
this.httpClient.get("----")
.pipe(map(Response => Response))
.subscribe((res: any) => {
this.searchResultObject = res;
this.allSearchResultArray.push(this.searchResultObject);
this.dataService.changeParam(this.allSearchResultArray)
resolve(this.searchResultObject );
});
});
}
passDataToService(){
this.dataService.allPassedData.next(this.allSearchResultArray);
}
}
data.service.ts
export class DataService {
allPassedData: any
constructor() { }
storePassedObject(passedData:any){
this.allPassedData.next(passedData);
}
retrievePassedObject(){
return this.allPassedData;
}
}
history-page.component.ts
export class HistoryPageComponent implements OnInit {
historyData : any = [];
constructor(private dataService: DataService) { }
ngOnInit(): void {
this.historyData = this.dataService.retrievePassedObject()
}
}
I am unable to retrieve data via this designed code.
First create subject in service and make it as observable
data.service.ts
export class DataService {
private allPassedData = new Subject<any>();
allPassedData$ = this.allPassedData.asObservable();
constructor() { }
setPassedData(retrievedData: any) {
this.allPassedData.next(retrievedData);
}
}
Now set the data in the observable
search-page.component.ts
passDataToService() {
this.dataService.setPassedData(this.allSearchResultArray);
}
history-page.component.ts
ngOnInit(): void {
// for retrieval of data in history component
this.dataService.allPassedData$.subscribe((data) => {
this.historyData = data
})
}

Circular trap in Builder method while implementing in Javascript

I was trying to implement a Builder pattern in Javascript using modularity, where I got caught in a circular dependencies-like situation. My file structure looks something like this,
index.js
import PersonBuilder from "./PersonBuilder.js";
let pb = new PersonBuilder();
let person = pb.lives.in('jaipur').at('ajmer Road')
.age.of(32).build();
Person.js
class Person
{
constructor()
{
this.city = this.street = this.name = "";
this.age = 0;
}
toString(){
return `${this.name} from ${this.city} lives at ${this.street} is ${this.age} years old`;
}
}
export default Person;
PersonBuilder.js
import Person from "./Person.js";
import PersonAgeBuilder from "./PersonAgeBuilder.js";
import PersonAddressBuilder from "./PersonAddressBuilder.js";
class PersonBuilder
{
constructor(person = new Person)
{
this.Person = person;
}
get lives()
{
return new PersonAddressBuilder(this.person);
}
get age()
{
return new PersonAgeBuilder(this.person);
}
build()
{
return this.person;
}
}
export default PersonBuilder;
PersonAddressBuilder.js
import PersonBuilder from "./PersonBuilder.js";
class PersonAddressBuilder extends PersonBuilder
{
constructor(person)
{
super(person);
}
in(city){
this.person.city = city;
return this;
}
at(street)
{
this.person.street = street;
return this;
}
}
export default PersonAddressBuilder;
PersonAgeBuilder.js
import PersonBuilder from "./PersonBuilder.js";
class PersonAgeBuilder extends PersonBuilder
{
constructor(person)
{
super(person);
}
of(age){
this.person.age = age;
}
}
export default PersonAgeBuilder;
When I am calling index.js on my browser I got the following error:
Uncaught ReferenceError: Cannot access 'PersonBuilder' before initialization
at PersonAgeBuilder.js:4
how can I solve this?

LocalStorage not displaying array of todolist after refreshing page

I'm currently developing a ToDo List using Angular 8. When I enter in a task for my ToDo list it saves it in the Localstorage but when I refresh my page my tasks are gone but are still stored inside the localstorage of the browser.
How do I keep my tasks from disappearing after refreshing the browser, when they're still saved in LocalStorage?
import { Component, OnInit } from '#angular/core';
import { ToDo, IToDo } from './todo.model';
import { HttpClient } from '#angular/common/http';
import { LocalStorageService } from '../localStorageService';
import { ActivatedRoute, Router } from '#angular/router';
import { IUser } from '../login/login.component';
import { ToastService } from '../toast/toast.service';
#Component({
// tslint:disable-next-line: component-selector
selector: 'todolist',
templateUrl: './todo.component.html',
styleUrls: ['./todo.component.css']
})
export class ToDoComponent implements OnInit {
todos: Array<IToDo> = [];
inputtask = "";
toDoParams = '';
localStorageService: LocalStorageService<IToDo>;
currentUser: IUser;
modal: any;
constructor(
private http: HttpClient,
private activatedRoute: ActivatedRoute,
private router: Router) {
this.localStorageService = new LocalStorageService('todos');
}
private toastService: ToastService;
async ngOnInit() {
const currentUser = this.localStorageService.getItemsFromLocalStorage('user');
console.log('from todos component', currentUser);
if (currentUser == null) {
this.router.navigate(['login']);
}
}
// Creating a to do item by clicking on the Enter Button
addToDo(todo: string) {
const td = {
id: 1,
task: todo,
editing: false
}
if (todo === '') {
alert('You must enter in a task TO DO!')
} else {
this.todos.push(td);
}
this.saveItemsToLocalStorage(this.todos);
}
delete(index: number) {
this.todos.splice(index, 1);
console.log("index", index);
this.saveItemsToLocalStorage(this.todos);
}
clear() {
this.todos = [];
console.log('index', this.todos)
this.saveItemsToLocalStorage(this.todos);
}
getItemsFromLocalStorage(key: string) {
const savedToDo = JSON.parse(localStorage.getItem(key));
console.log('from getItemsFromLocalStorage savedItems', savedToDo);
return this.localStorageService.getItemsFromLocalStorage(key);
return savedToDo;
}
saveItemsToLocalStorage(todos: Array<IToDo>) {
todos = this.sortByID(todos);
return this.localStorageService.saveItemsToLocalStorage(todos);
const savedToDo = localStorage.setItem('todos', JSON.stringify(todos));
console.log('from saveItemsToLocalStorage savedToDos: ', savedToDo);
return savedToDo;
}
sortByID(todos: Array<IToDo>) {
todos.sort((prevToDo: IToDo, presToDo: IToDo) => {
return prevToDo.id > presToDo.id ? 1 : -1;
});
console.log('the sorted ToDos', this.todos);
return this.todos;
}
logout() {
// clear localStorage
this.localStorageService.clearItemFromLocalStorage();
// navigate to login page
this.router.navigate(['']);
}
}
Here is the LocalStorageService file below
export class LocalStorageService<T> {
constructor(private key: string) {
}
saveItemsToLocalStorage(todos: Array<T> | T) {
const savedToDos = localStorage.setItem(this.key, JSON.stringify(todos));
console.log('from saveItemsToLocalStorage savedToDos: ', savedToDos);
return savedToDos;
}
getItemsFromLocalStorage(key?: string) {
let savedItems;
if (key != null) {
const items = null;
savedItems = JSON.parse(localStorage.getItem(key));
console.log('from getItemFromLocalStorage key: ', key, 'savedItems: ', savedItems);
} else {
savedItems = JSON.parse(localStorage.getItem(this.key));
}
return savedItems;
}
clearItemFromLocalStorage(key?: string) {
if (key != null) {
const items = null;
localStorage.setItem(key, JSON.stringify(items));
} else {
localStorage.clear();
}
}
}
Hey so when the page reloads angular loses context of the view so it has to render it again. You have all the working code here to make it work you just have to change the ngOnInit page load event so it reads them again and binds them to the property so angular can show them in the UI. Also bare in mind you call clearItemFromLocalStorage on logout so this won't grab them if they logout and then log back in, but i guess that was expected due to the code you have wrote.
The below should slot in and work for you:
async ngOnInit() {
const currentUser = this.localStorageService.getItemsFromLocalStorage('user');
console.log('from todos component', currentUser);
if (currentUser == null) {
await this.router.navigate(['login']);
} else {
// if user is logged in go and find any items from local storage and bind
// to the view
const toDoItems = this.localStorageService.getItemsFromLocalStorage('todos');
if (toDoItems && Array.isArray(toDoItems)) {
this.todos = toDoItems;
}
}
}

error TS2559: Type 'BookInterface[]' has no properties in common with type 'BookInterface'

Dear I am developing a page with Angular 7 and I am presented with the error TS2559: Type 'BookInterface[]' has no properties in common with type 'BookInterface', I have changed the code but I still can not find the solution, I leave the code below, the error is thrown in the method getListBooks(): this is my file list-books.component.ts
import { BookInterface } from './../../../models/book';
import { DataApiService } from './../../../services/data-api.service';
import { Component, OnInit } from '#angular/core';
import {NgForm} from '#angular/forms';
#Component({
selector: 'app-list-book',
templateUrl: './list-book.component.html',
styleUrls: ['./list-book.component.css']
})
export class ListBookComponent implements OnInit {
constructor(private dataApi: DataApiService) { }
private books: BookInterface = {};
ngOnInit() {
this.getListBooks();
}
getListBooks() {
this.dataApi.getAllBooks().subscribe(books => {
this.books = books;
});
}
onDelete() {
console.log('LIBRO ELIMINADO');
}
}
I also leave the code of my data-api.service.ts from where I call the interface
import { map } from 'rxjs/operators';
import { Observable } from 'rxjs/internal/Observable';
import { Injectable } from '#angular/core';
import { AngularFirestore, AngularFirestoreCollection, AngularFirestoreDocument } from '#angular/fire/firestore';
import { BookInterface } from '../models/book';
#Injectable({
providedIn: 'root'
})
export class DataApiService {
constructor(private afs: AngularFirestore) {
this.bookCollecction = afs.collection<BookInterface>('books');
this.books = this.bookCollecction.valueChanges();
}
private bookCollecction: AngularFirestoreCollection<BookInterface>;
private books: Observable<BookInterface[]>;
private bookDoc: AngularFirestoreDocument<BookInterface>;
private book: Observable<BookInterface>;
getAllBooks() {
return this.books = this.bookCollecction.snapshotChanges()
.pipe(map( changes => {
return changes.map( action => {
const data = action.payload.doc.data() as BookInterface;
data.id = action.payload.doc.id;
return data;
});
}));
}
// metodo que trae un libro a traves de su id
getOneBook(idBook: string) {
this.bookDoc = this.afs.doc<BookInterface>(`books/${idBook}`);
return this.book = this.bookDoc.snapshotChanges().pipe(map(action => {
if (action.payload.exists === false){
return null;
} else {
const data = action.payload.data() as BookInterface;
data.id = action.payload.id;
return data;
}
}));
}
addBook(book: BookInterface): void {
this.bookCollecction.add(book);
}
updateBook(book: BookInterface): void {
let idBook = book.id;
this.bookDoc = this.afs.doc<BookInterface>(`books/${idBook}`);
this.bookDoc.update(book);
}
deleteBook(idBook: string): void {
this.bookDoc = this.afs.doc<BookInterface>(`books/${idBook}`);
this.bookDoc.delete();
}
}
The version of typescript that I am currently using is Version 2.7.2, but also update it without solving the problem
You need to change the following:
private books: BookInterface = {};
to:
private books: BookInterface[] = [];

Javascript es6 class inheritance

Can someone please explain to me why calling a parent function from child is reseting parent class variables.
class Garages {
constructor() {
this.garages = {};
}
addGarage(id) {
this.garages[id] = {id};
return this.garages[id];
}
getGarage(id) {
alert(this.garages[id]); //why undefined?
}
}
class Cars extends Garages {
constructor() {
super();
this.cars = [];
}
getGarageByID(id) {
this.getGarage(id)
}
}
const cars = new Cars();
const garages = new Garages();
console.log(garages.addGarage("one"))
cars.getGarageByID("one")
FIDDLE
beacuse the instance of cars is differnet from garages , you should write like this:
alert(cars.addGarage("one")) //alerts object
alert(cars.getGarageByID("one"))
Issue #1 is that you are adding to one instance and asking another to get you the value.
Issue #2 is that you are not returning anything from getGarageByID hence you get undefined.
Change your code to this:
class Garages {
constructor() {
this.garages = {};
}
addGarage(id) {
this.garages[id] = {id};
return this.garages[id];
}
getGarage(id) {
return this.garages[id];
}
}
class Cars extends Garages {
constructor() {
super();
this.cars = [];
}
getGarageByID(id) {
return this.getGarage(id)
}
}
const cars = new Cars();
console.log(cars.addGarage("one"))
console.log(cars.getGarageByID("one"))
And you should get both to print.

Categories