I am learning WebGL and started developing an Sketch app using p5.js and angular. I have defined boolean variables in the component file so that based on that i want to trigger specific function like ellipse, rectangle, line etc in the draw function. These boolean variables are managed by buttons in another component.
I am getting error as core.js:6014 ERROR TypeError: Cannot read property 'isRectangleMode' of undefined
Component file:
import { Component, OnInit } from '#angular/core';
import * as p5 from 'p5';
import { Subscription } from 'rxjs';
import { HomeService } from '../home.service';
#Component({
selector: 'app-doodle-area',
templateUrl: './doodle-area.component.html',
styleUrls: ['./doodle-area.component.css']
})
export class DoodleAreaComponent implements OnInit {
private p5Init : any;
modeSubs : Subscription;
modeSelected : string = null;
isCircleMode : boolean = false;
isEllipseMode : boolean = false;
isRectangleMode : boolean = false;
isLineMode : boolean = false;
isPointMode : boolean = false;
isBrushMode : boolean = false;
isPenMode : boolean = false;
constructor(private homeService : HomeService) { }
ngOnInit() {
this.createCanvas();
this.homeService.modeSelected
.subscribe(modeSelected => {
this.modeSelected = modeSelected;
console.log(this.modeSelected);
if(this.modeSelected) {
this.modeReset();
if(this.modeSelected === "circle") {
this.isCircleMode = true;
} else if(this.modeSelected === 'ellipse') {
this.isEllipseMode = true;
} else if(this.modeSelected === 'rectangle') {
this.isRectangleMode = true;
} else if(this.modeSelected === 'line') {
this.isLineMode = true;
} else if(this.modeSelected === 'point') {
this.isPointMode = true;
} else if(this.modeSelected === 'brush') {
this.isBrushMode = true;
} else if(this.modeSelected === 'pen') {
this.isPenMode = true;
}
}
});
}
private modeReset() {
this.isCircleMode = false;
this.isEllipseMode = false;
this.isRectangleMode = false;
this.isLineMode = false;
this.isPointMode = false;
this.isBrushMode = false;
this.isPenMode = false;
}
private createCanvas() {
this.p5Init = new p5(this.doodleArea);
}
private doodleArea(p : any) {
p.setup = () => {
p.createCanvas(p.windowWidth - 440, p.windowHeight - 200).parent('doodle-area');
p.background(206,214,224);
p.createP("Hello");
}
p.draw = () => {
if(this.isRectangleMode) {
console.log("Rectangle");
}
p.stroke(0);
if(p.mouseIsPressed === true) {
p.line(p.mouseX, p.mouseY, p.pmouseX, p.pmouseY);
}
}
}
}
Screenshot of the console:
This is issue is because of the scope. Here inside the callback function doodleArea, the scope is not component scoped (this). Here this is undefined and we can not access isRectangleMode of undefined. The possible solution for this is:
In .ts modify the createCanvas() with code given below:
private createCanvas() {
const doodleArea = s => {
s.setup = () => {
let canvas = s.createCanvas(s.windowWidth - 440, s.windowHeight - 200);
canvas.parent("doodle-area");
s.draw = () => {
if (this.isRectangleMode) {
console.log("Rectangle");
}
s.stroke(0);
if (s.mouseIsPressed === true) {
s.line(s.mouseX, s.mouseY, s.pmouseX, s.pmouseY);
}
};
s.keyPressed = () => {
if (s.key === 'c') {
window.location.reload();
}};};
};
this.p5Init = new p5(doodleArea);
}
Below is the sample code of the same:
https://stackblitz.com/edit/angular-s-p5-angular?file=src%2Fapp%2Fapp.component.ts
https://angular-s-p5-angular.stackblitz.io
Hope this will help.
Related
I am using resumablejs library with Angular 7. When trying to upload files using resumable, it works till 1.5 GB without any issue, but when file size > 1.5 GB, it works in some cases and crashes in some cases. Not sure what is causing the issue.
It works fine without any issue on Firefox.
How can i make it work with Chrome.
Below is the component. Here we are calculating file size and then displaying it on screen.
export class ResumableAttachmentComponent
implements AfterViewInit, OnDestroy, OnChanges, OnInit {
#Output() fileSuccess = new EventEmitter<any>();
#Output() fileError = new EventEmitter<any>();
#Output() error = new EventEmitter<any>();
#Output() progress = new EventEmitter<any>();
#Output() pause = new EventEmitter<any>();
#Output() complete = new EventEmitter<any>();
#Output() uploadStart = new EventEmitter<any>();
#Output() uploadCancel = new EventEmitter<any>();
#Output() fileTypeError = new EventEmitter<any>();
#Output() removeBannerImage = new EventEmitter<any>();
#Output() onComponentInit = new EventEmitter<any>();
#Input() allowDirectorySelect = false;
#Input() maxFileSize = 1024 * 1024 * 1024 * 5; // 5GB
#Input() maxFiles = 1; // max number of file allowed
#Input() multiple = false;
#Input() pausable = false;
#Input() entityType: string;
#Input() entityIdentifierId: string;
#Input() categoryId: string;
#Input() chunkSize = 1024 * 1024 * 5; // 5 MB per chunk by default
#Input() checkBeforeUpload: () => boolean;
#Input() showCategory: boolean = true;
#Input() showUploadButton: boolean = true;
#Input() showDelete: boolean = false;
#Input() showUploadMessage: boolean = false;
#Input() fileType: string[] = []; // Allowing for both [extension, .extension, mime/type, mime/*]
#Input() theme: string = 'full';
#Input() permissionLevel: number;
#Input() permission: number;
#Input() bannerAttachment: any = null;
#Input() isUploadDisabled: any = false;
#Input() hasThumbnails: boolean = false;
Permissions = Permissions;
PermissionLevel = PermissionLevel;
fileSizeGreaterThanMaxAllowed = false;
numberOfFilesGreaterThanMaxAllowed = false;
// indicate that the upload is paused by user or not
paused = false;
progressBarElt: any;
querySet: boolean = false;
// text to show on the upload button depending on the fact the file upload is paused or not
uploadBtnText = localize('general_Upload');
filesToUpload: Resumable.ResumableFile[] = [];
disableUploadButton = true;
disablePauseButton = true;
disableCancelButton = true;
isChunking = false;
// #ts-ignore
resumable: Resumable;
supportResumable = false;
currentUser: IUserProfile;
baseUrl = titanApiUrl;
destroySubject = new Subject<any>();
showSelectButton: boolean;
#Input() gridSupport: {
gridData: SimpleGrid;
type: 'extend' | null;
onRowSelect: () => {};
};
resumableUploadedFiles: IResumableFileData;
backboneObservable$: Subscription;
showCommentsDialog: boolean;
tireComment: string;
constructor(
private userProfileService: UserProfileService,
private backbone: BackboneService,
private eltRef: ElementRef,
private renderer: Renderer2,
private notifyService: NotificationService,
private confirmationService: ConfirmationDialogService,
private router: Router,
private userPermissionHelper: UserPermissionHelper,
private attachmentService: AttachmentService
) {
this.currentUser = this.userProfileService.userProfile;
// cancel the file upload when user is navigating away from the page that contains the component
this.router.events
.filter(e => e instanceof NavigationStart)
.distinctUntilChanged()
.takeUntil(this.destroySubject.asObservable())
.subscribe((e: NavigationStart) => {
if (this.resumable && this.resumable.isUploading()) {
this.cancelUpload();
}
});
this.showSelectButton = true;
}
ngOnInit() {
this.checkPermission();
this.backboneObservable$ = this.backbone.message.subscribe(item => {
if (
item.type === BBMessageType.Resumable &&
item.subtype === BBMessageSubType.Resumable_Files_Attached
) {
this.resumableUploadedFiles = item.message;
}
});
this.duplicatesDialog.onSubmit = () => {
this.duplicatesDialog.show = false;
this.resumable.files.forEach(item => {
item.resumableObj.opts.query['overwrite'] =
this.duplicatesDialog.confirmedOverwrite.indexOf(
item.fileName
) >= 0;
});
};
this.onComponentInit.emit(this);
}
reset() {
// reset error flags
this.fileSizeGreaterThanMaxAllowed = false;
this.numberOfFilesGreaterThanMaxAllowed = false;
this.removeAllFiles();
this.isChunking = false;
this.paused = false;
this.uploadBtnText = localize('general_Upload');
//this.hideProgressBar = true
this.renderer.setStyle(this.progressBarElt, 'width', 0);
this.disableCancelButton = true;
this.disablePauseButton = true;
this.disableUploadButton = true;
}
ngOnDestroy() {
this.destroySubject.next();
this.backboneObservable$.unsubscribe();
}
ngAfterViewInit() {
if (!this.querySet) {
this.setResumableQuery();
}
}
hasUploadPermission: boolean = true;
ngOnChanges(changes: SimpleChanges) {
let self = this;
//If Test Template
if (
changes.hasOwnProperty('entityIdentifierId') &&
changes.entityIdentifierId.currentValue
) {
if (!self.querySet) {
self.setResumableQuery();
}
if (self.resumable) {
self.entityIdentifierId =
changes.entityIdentifierId.currentValue;
self.resumable.opts.query['entityId'] =
changes.entityIdentifierId.currentValue;
self.resumable.opts.query['entityIdentifierId'] =
changes.entityIdentifierId.currentValue;
}
}
if (changes.hasOwnProperty('entityType') && self.resumable) {
self.resumable.opts.query['entityType'] = this.entityType;
}
//Hijack query to add new/selected category id
if (changes.hasOwnProperty('categoryId') && self.resumable) {
self.resumable.opts.query['categoryId'] = this.categoryId;
}
if (changes.permission && changes.permissionLevel) {
self.hasUploadPermission = this.userPermissionHelper.checkPermission(
this.permission,
this.permissionLevel
);
}
if (changes.fileType && self.resumable) {
self.resumable.opts.fileType = this.fileType;
}
}
submitComment() {
this.resumable.opts.query['comment'] = this.tireComment;
this.resumable.upload();
this.tireComment = '';
this.showCommentsDialog = false;
}
setResumableQuery() {
let maxFileAllowed = this.multiple ? undefined : this.maxFiles; // undefined => allow to upload multiple file
//
// extra parameters to include in the multipart POST with data
let query = {};
if (this.entityType) {
query['entityType'] = this.entityType;
}
if (this.entityIdentifierId) {
query['entityIdentifierId'] = this.entityIdentifierId;
}
if (this.categoryId) {
query['categoryId'] = this.categoryId;
}
if (this.hasThumbnails) {
query['createThumbnail'] = true;
} else {
query['createThumbnail'] = false;
}
let fileUploadOptions: Resumable.ConfigurationHash = {
target: `${this.baseUrl}ResumableFile/Upload`,
simultaneousUploads: 1,
maxFiles: maxFileAllowed,
chunkSize: this.chunkSize,
forceChunkSize: true,
fileParameterName: 'file', // The name of the multipart POST parameter to use for the file chunk
query,
headers: {
userId: this.currentUser.id,
tenantId: this.currentUser.defaultTenantId
},
fileType: this.fileType,
fileTypeErrorCallback: this.onFileTypeError.bind(this)
};
// #ts-ignore
this.resumable = new Resumable(fileUploadOptions);
this.supportResumable = this.resumable.support; // check if the current browser suport resumable
// add event only if the browser support resumable upload
if (this.supportResumable) {
this.progressBarElt = this.eltRef.nativeElement.querySelector(
'.t-resumable-attachment-progress-bar-indicator'
);
let chooseFileBtn;
if (this.theme === 'icon') {
chooseFileBtn = this.eltRef.nativeElement.querySelector(
'.icon-theme-resumable'
);
} else {
chooseFileBtn = this.eltRef.nativeElement.querySelector(
'.choose-file'
);
}
if (chooseFileBtn) {
this.resumable.assignBrowse(
chooseFileBtn,
this.allowDirectorySelect
);
this.resumable.assignDrop(
this.eltRef.nativeElement.querySelector('.drop-area')
);
} else {
setTimeout(() => {
if (!this.querySet) {
this.setResumableQuery();
}
}, 400);
return;
}
this.setEvents();
}
this.querySet = true;
}
uploadTheFile() {
if (
this.checkBeforeUpload &&
typeof this.checkBeforeUpload === 'function'
) {
let checkResult = this.checkBeforeUpload();
// start the upload only if the check function return true
if (checkResult) {
// this.onUploadStart()
this.resumable.upload();
}
} else if (
this.checkBeforeUpload &&
typeof this.checkBeforeUpload !== 'function'
) {
throw new Error(
"The 'checkBeforeUpload' attribute must be a function."
);
} else {
// this.onUploadStart()
this.resumable.upload();
/* temporarily commenting the Comment popup while uploading file for Tire Model Request
if (this.entityType == 'TireModelSpecs') {
this.showCommentsDialog = true;
} else {
this.resumable.upload();
}*/
}
}
pauseFile() {
this.resumable.pause();
}
cancelUpload() {
this.resumable.cancel();
}
private setEvents() {
this.resumable.on('error', this.onError.bind(this));
this.resumable.on('fileError', this.onFileError.bind(this));
this.resumable.on('pause', this.onPause.bind(this));
this.resumable.on('complete', this.onComplete.bind(this));
this.resumable.on('fileSuccess', this.onFileSuccess.bind(this));
this.resumable.on('cancel', this.onUploadCancel.bind(this));
this.resumable.on('uploadStart', this.onUploadStart.bind(this));
//this.resumable.on('uploadStart', this.startUploadAfterCheckIsOk)
this.resumable.on('fileProgress', this.onProgress.bind(this));
this.resumable.on('fileAdded', this.onFileAdded.bind(this));
this.resumable.on('chunkingStart', this.onChunkingStart.bind(this));
this.resumable.on(
'chunkingComplete',
this.onChunkingComplete.bind(this)
);
}
#Output() onFileAdd = new EventEmitter();
private onFileAdded(file: ResumableFile, event) {
this.numberOfFilesGreaterThanMaxAllowed = false;
this.fileSizeGreaterThanMaxAllowed = false;
this.isDragOver = false;
//Getting Preview Image
let resumableFile: ResumableFile = this.resumable.files.find(item => {
// #ts-ignore
return file.file.uniqueIdentifier === item.uniqueIdentifier;
});
// #ts-ignore
resumableFile.fileReader = new FileReader();
// #ts-ignore
resumableFile.fileReader.readAsDataURL(file.file);
/**
* Show preview only if MIME type is of image type
*/
if (resumableFile.file.type.startsWith('image')) {
resumableFile.isPreviewSupported = true;
}
/**
* TODO: Check if total size was being looked at here..
*/
// #ts-ignore
if (this.resumable.getSize() > this.maxFileSize) {
this.fileSizeGreaterThanMaxAllowed = true;
this.filesToUpload = [...this.resumable.files];
} else if (
!this.multiple &&
this.resumable.files &&
this.resumable.files.length > this.maxFiles
) {
this.numberOfFilesGreaterThanMaxAllowed = true;
} else {
this.filesToUpload = [...this.resumable.files]; // get the updated list of files to upload
this.disableUploadButton = false;
this.renderer.setStyle(this.progressBarElt, 'width', 0);
}
this.disableCancelButton = false;
if (this.theme === 'icon') {
this.uploadTheFile();
} else {
this.duplicatesDialog.duplicatesArray = [];
this.checkForDuplicates();
}
this.setRealLastModifiedDate(resumableFile, file.file.lastModified);
this.onFileAdd.emit(this.filesToUpload);
}
setRealLastModifiedDate(file: ResumableFile, dateMS) {
file['resumableObj'].opts.query['documentLastModifiedByDate'] = moment(
dateMS
).format('YYYY/MM/DD HH:mm');
}
duplicatesDialog: {
duplicatesArray: any[];
confirmedOverwrite: any[];
show: boolean;
onSubmit: any;
} = {
duplicatesArray: [],
confirmedOverwrite: [],
show: false,
onSubmit: () => {}
};
checkForDuplicates() {
if (
this.resumableUploadedFiles &&
this.currentUser.tenantFeatureMap.overwriteFile &&
this.resumableUploadedFiles.categoryId === this.categoryId &&
this.resumableUploadedFiles.entityIdentifierId ===
this.entityIdentifierId
) {
this.filesToUpload.forEach(item => {
if (
this.resumableUploadedFiles.data.indexOf(item.fileName) >= 0
) {
this.duplicatesDialog.duplicatesArray.push(item.fileName);
} else {
item['resumableObj'].opts.query['overwrite'] = false;
}
});
}
if (this.duplicatesDialog.duplicatesArray.length > 0) {
this.duplicatesDialog.show = true;
}
}
private onPause() {
this.paused = true;
this.disableUploadButton = false;
this.uploadBtnText = localize('general_Resume');
this.pause.emit();
}
onComplete() {
this.complete.emit();
//Reset filesToUpload after completion
this.removeAllFiles();
}
OnRemoveBannerImg() {
this.confirmationService.setConfirm({
message: localize('general_ConformMessageForDelete'),
header: localize('general_Delete'),
accept: () => {
this.removeBannerImage.emit();
},
reject: () => {}
});
}
// `message` is the response body from the server.
private onFileSuccess(file: ResumableFile, message: any) {
if (this.showUploadMessage) {
this.notifyService.notify({
severity: 'success',
summary: localize('general_Success'),
detail: localize('general_MessageSuccessFileUploaded')
});
}
this.filesToUpload = [];
this.fileSuccess.emit({ file, message });
this.disableCancelButton = true;
this.disablePauseButton = true;
this.disableUploadButton = true;
}
// error on a specific file
private onFileError(file: ResumableFile, message: any) {
this.fileError.emit({ file, message });
}
// general error
private onError(message: any, file: ResumableFile) {
this.error.emit({ file, message });
}
onUploadStart() {
//this.hideProgressBar = false
this.uploadStart.emit(this.resumable.files.length);
this.paused = false;
this.disableUploadButton = true;
this.uploadBtnText = localize('general_Upload');
this.disableCancelButton = false;
this.disablePauseButton = false;
this.disableUploadButton = true;
}
private onProgress(file: ResumableFile) {
let fileClone: any = { ...file };
fileClone.uploaded = file.progress(false);
let totalProgress = this.resumable.progress();
let progressPercentage = Math.floor(totalProgress * 100) + '%';
this.renderer.setStyle(
this.progressBarElt,
'width',
progressPercentage
);
this.progress.emit({ file: fileClone, uploaded: totalProgress });
}
/**
* return individual file upload progress
*/
parseProgress(file: ResumableFile) {
return (
Math.round(Math.floor(file.progress(false) * 100) * 10) / 10 + '%'
);
}
private onUploadCancel() {
this.paused = false;
this.uploadBtnText = localize('general_Upload');
this.filesToUpload = this.resumable.files;
this.renderer.setStyle(this.progressBarElt, 'width', 0);
this.uploadCancel.emit();
this.disableCancelButton = true;
this.disablePauseButton = true;
this.disableUploadButton = true;
}
private removeAllFiles() {
let copy = [...this.resumable.files];
copy.forEach((f: any) => this.resumable.removeFile(f));
this.filesToUpload = this.resumable.files;
this.duplicatesDialog.confirmedOverwrite = [];
this.duplicatesDialog.duplicatesArray = [];
}
private onChunkingStart() {
this.isChunking = true;
}
private onChunkingComplete() {
this.isChunking = false;
}
private onFileTypeError(file, errorCount) {
this.fileTypeError.emit({ file, errorCount });
}
removeFile(file: any) {
this.resumable.removeFile(file);
// update the list when a file is removed
this.filesToUpload = this.resumable.files;
this.onFileAdd.emit(this.filesToUpload);
}
getFileSize(sizeInOctet: number) {
sizeInOctet = +sizeInOctet; // convert to number in case ng pass the value as string
let KB = 1024;
let MB = 1024 * 1024;
let GB = 1024 * 1024 * 1024;
if (sizeInOctet >= KB) {
if (sizeInOctet >= MB) {
if (sizeInOctet >= GB) {
return `${(sizeInOctet / GB).toFixed(2)} GB`;
}
return `${(sizeInOctet / MB).toFixed(2)} MB`;
}
return `${(sizeInOctet / KB).toFixed(2)} KB`;
}
return `${sizeInOctet} Bytes`;
}
// case multiple file
// Hide pause/resume when the upload has completed
// Show pause, hide resume on upload start
isDragOver: boolean = false;
onDrop($event) {
this.isDragOver = false;
}
allowDrop($event) {
this.isDragOver = true;
}
onLeave() {
this.isDragOver = false;
}
hasAccess: boolean = false;
hasReadAccess: boolean = false;
hasDeleteAccess: boolean = false;
hasCreateAccess: boolean = false;
checkPermission() {
if (
this.permission &&
this.permissionLevel &&
this.entityIdentifierId &&
this.entityType
) {
this.hasDeleteAccess =
this.userPermissionHelper.checkPermission(
this.permission,
PermissionLevel.Delete
) ||
this.userPermissionHelper.checkSpecialPermission(
this.permission,
PermissionLevel.Delete,
this.entityIdentifierId,
this.entityType
);
this.hasReadAccess =
this.userPermissionHelper.checkPermission(
this.permission,
PermissionLevel.Read
) ||
this.userPermissionHelper.checkSpecialPermission(
this.permission,
PermissionLevel.Read,
this.entityIdentifierId,
this.entityType
);
this.hasCreateAccess =
this.userPermissionHelper.checkPermission(
this.permission,
PermissionLevel.Create
) ||
this.userPermissionHelper.checkSpecialPermission(
this.permission,
PermissionLevel.Create,
this.entityIdentifierId,
this.entityType
);
this.hasAccess =
this.hasCreateAccess ||
this.hasDeleteAccess ||
this.hasReadAccess;
}
}
checkFileList() {
if (!this.resumable) {
return !this.isChunking;
} else {
return !this.isChunking && !this.resumable.isUploading();
}
}
downloadAttachment(id) {
this.attachmentService.download(id);
}
viewLog(id) {
this.attachmentService.getLogByDocumentId;
}
previewFileUrl: string = '';
previewDialog: boolean = false;
expandImage(previewFileUrl) {
this.previewFileUrl = previewFileUrl;
this.previewDialog = true;
}
}
I created this script, however the cache cleaning warning appears in the debug console which is not defined. How can I solve it?
I uploaded the code here https://codepen.io/stiac/pen/ExPjgwe
class NotificationBanner {
constructor(el) {
this.storageKey = 'notifications'
this.el = el
this.id = this.el.dataset.id
this.el.querySelector(".closebutton").onclick = () => this.close()
this.showUnlessDismissed()
}
show() {
this.el.hidden = false
}
close() {
this.el.remove()
this.updateLocalStorage()
}
showUnlessDismissed() {
if(this.getLocalStorage().includes(this.id)) {
this.close()
}
else {
this.show()
}
}
updateLocalStorage() {
const dismissedNotifications = this.getLocalStorage()
if(!dismissedNotifications.includes(this.id)) {
dismissedNotifications.push(this.id)
localStorage.setItem(this.storageKey, JSON.stringify(dismissedNotifications))
}
}
getLocalStorage() {
return JSON.parse(localStorage.getItem(this.storageKey)) || []
}
}
class NotificationBanners {
constructor() {
const notifications = [...document.querySelectorAll(".notification-banner")];
notifications.forEach(function(notification) {
return new NotificationBanner(notification);
})
}
}
new NotificationBanners()
clearcache.onclick = e => localStorage.setItem('notifications', JSON.stringify([]))
It is a script to hide a message. I wish I could set a deadline to make it appear after a few days.
I have code listed below. All "Tree" class works fine. I need help with "makekDir" function (in Node class), it should create new children tree (directory). This code in "makekDir" function this.findNode(filepath) always return null. I can't find how to fix it. Can any one help, or give advice how to fix it p.s. sorry for the big chunk of code, don't know would it be understandable if I post only Node class
import path from 'path';
//this class works fine
class Tree {
constructor(key, meta, parent) {
this.parent = parent;
this.key = key;
this.meta = meta;
this.children = new Map();
}
getKey() {
return this.key;
}
getMeta() {
return this.meta;
}
addChild(key, meta) {
const child = new Tree(key, meta, this);
this.children.set(key, child);
return child;
}
getChild(key) {
return this.children.get(key);
}
hasChild(key) {
return this.children.has(key);
}
getDeepChild(dirs = []) {
if (dirs.length === 0 || !Array.isArray(dirs)) {
console.log('not array');
return null;
}
const [first, ...rest] = dirs;
console.log(first, ...rest);
console.log (this);
if (this.hasChild(first)) {
return rest.length === 0
? this.getChild(first)
: this.getChild(first).getDeepChild(rest);
}
return null;
}
}
class Node {
constructor() {
this.tree = new Tree('/', { type: 'dir' });
}
///// I need help with this function
makekDir(filepath) {
const { dir } = path.parse(filepath);
const subtree = this.findNode(filepath);
return subtree.addChild(dir, { type: 'dir' });
}
/////
findNode(filepath) {
const parts = filepath.split(path.sep).filter((item) => item !== '');
return parts.length === 0 ? this.tree : this.tree.getDeepChild(parts);
}
}
console.log(new Node().makekDir('/etc'));
Current config (cannot update it to latest):
"#angular/cli": "^7.3.9",
"primeng": "7.0.5",
I have a PrimeNG p-table that has lazy loaded data with pagination.
There is an issue open for it on PrimeNG GitHub too - https://github.com/primefaces/primeng/issues/8139
Stackblitz link is already attached in that issue so didn't create a new one.
Scenario:
One 1st page, some rows are selected via checkbox selection.
On 2nd page, Select All checkbox from the header is selected and all rows on 2nd page is auto-selected.
Now when navigated to the first page, the selections from here are reset. But the Select All checkbox in the header is still checked.
Would like to know if anyone has a workaround for this issue?
Any help is appreciated.
Edit:
Solution found in another similar GitHub issue: https://github.com/primefaces/primeng/issues/6482
Solution:
https://github.com/primefaces/primeng/issues/6482#issuecomment-456644912
Can someone help with the implementation of the override in an Angular 7/8 application. Not able to understand as how to get the TableHeaderCheckbox reference and override the prototype.
Well, the solution to the problem is still not added to the PrimeNG repo and so even the latest package does not have it solved.
For time being, use the solution mentioned in the question under Edit
To answer the question that I have asked under the Edit, check below:
// In some service file:
import { Table, TableHeaderCheckbox } from 'primeng/table';
import { ObjectUtils } from 'primeng/components/utils/objectutils';
import { uniq, each, intersection, map, remove } from 'lodash';
#Injectable()
export class BulkSelectAllPagesService {
overridePrimeNGTableMethods() {
TableHeaderCheckbox.prototype.updateCheckedState = function () {
const currentRows = map(this.dt.value, this.dt.dataKey);
const selectedRows = map(this.dt.selection, this.dt.dataKey);
this.rowsPerPageValue = this.dt.rows;
const commonRows = intersection(currentRows, selectedRows);
return commonRows.length === currentRows.length;
};
Table.prototype.toggleRowsWithCheckbox = function (event, check) {
let _selection;
if (!check) {
_selection = this.value.slice();
each(_selection, (row) => {
const match = {}; match[this.dataKey] = row[this.dataKey];
remove(this._selection, match);
});
} else {
_selection = check ? this.filteredValue ? this.filteredValue.slice() : this.value.slice() : [];
each(this._selection, (row) => {
const match = {}; match[this.dataKey] = row[this.dataKey];
remove(_selection, match);
});
this._selection = this._selection.concat(_selection);
}
this.preventSelectionSetterPropagation = true;
this.updateSelectionKeys();
this.selectionChange.emit(this._selection);
this.tableService.onSelectionChange();
this.onHeaderCheckboxToggle.emit({
originalEvent: event,
affectedRows: _selection,
checked: check
});
};
}
// In app.component.ts
import { Component, OnInit } from '#angular/core';
import { BulkSelectAllPagesService } from 'PATH_TO_THE_FILE/bulk-select-all-pages.service';
#Component({
selector: 'app-root',
templateUrl: './app.component.html'
})
export class AppComponent implements OnInit {
constructor(
private bulkSelectAllPagesService: BulkSelectAllPagesService) {
}
ngOnInit() {
this.bulkSelectAllPagesService.overridePrimeNGTableMethods();
}
}
Ofcourse need to include the service file in the providers[] in the app.module.ts
Will create a stackblitz and add later.
Improved version to handle rowspan grouped data:
overridePrimeNGTableMethods() {
TableHeaderCheckbox.prototype.updateCheckedState = function () {
const currentRows = map(this.dt.value, this.dt.dataKey);
const uniqueCurrentRows = uniq(currentRows);
const selectedRows = map(this.dt.selection, this.dt.dataKey);
this.rowsPerPageValue = this.dt.rows;
const commonRows = intersection(currentRows, selectedRows);
if (currentRows.length) {
return commonRows.length === uniqueCurrentRows.length;
} else {
return false;
}
};
Table.prototype.toggleRowWithCheckbox = function (event, rowData) {
const findIndexesInSelection = (selection: any = [], data: any = {}, dataKey: any) => {
const indexes = [];
if (selection && selection.length) {
selection.forEach((sel: any, i: number) => {
if (data[dataKey] === sel[dataKey]) {
indexes.push(i);
}
});
}
return indexes;
};
this.selection = this.selection || [];
const selected = this.isSelected(rowData);
const dataKeyValue = this.dataKey ? String(ObjectUtils.resolveFieldData(rowData, this.dataKey)) : null;
this.preventSelectionSetterPropagation = true;
if (selected) {
const selectionIndexes = findIndexesInSelection(this.selection, rowData, this.dataKey);
const selectedItems = this.selection.filter((val: any) => {
return val[this.dataKey] === rowData[this.dataKey];
});
this._selection = this.selection.filter((val: any, i: number) => {
return selectionIndexes.indexOf(i) === -1;
});
this.selectionChange.emit(this.selection);
selectedItems.forEach((selectedItem: any, index: number) => {
this.onRowUnselect.emit({ originalEvent: event.originalEvent, index: event.rowIndex + index, data: selectedItem, type: 'checkbox' });
});
delete this.selectionKeys[rowData[this.dataKey]];
} else {
let rows = [rowData];
if (dataKeyValue) {
rows = this.value.filter(val => {
return (val[this.dataKey]).toString() === dataKeyValue;
});
}
this._selection = this.selection ? this.selection.concat(rows) : rows;
this.selectionChange.emit(this.selection);
this.onRowSelect.emit({ originalEvent: event.originalEvent, index: event.rowIndex, data: rowData, type: 'checkbox' });
if (dataKeyValue) {
this.selectionKeys[dataKeyValue] = 1;
}
}
this.tableService.onSelectionChange();
if (this.isStateful()) {
this.saveState();
}
};
Table.prototype.toggleRowsWithCheckbox = function (event, check) {
let _selection;
if (!check) {
_selection = this.value.slice();
each(_selection, (row) => {
const match = {}; match[this.dataKey] = row[this.dataKey];
remove(this._selection, match);
});
} else {
_selection = check ? this.filteredValue ? this.filteredValue.slice() : this.value.slice() : [];
each(this._selection, (row) => {
const match = {}; match[this.dataKey] = row[this.dataKey];
remove(_selection, match);
});
this._selection = this._selection.concat(_selection);
}
this.preventSelectionSetterPropagation = true;
this.updateSelectionKeys();
this.selectionChange.emit(this._selection);
this.tableService.onSelectionChange();
this.onHeaderCheckboxToggle.emit({
originalEvent: event,
affectedRows: _selection,
checked: check
});
};
}
First I would like to say I have been trying to get this to work for over a year. I have tried a majority of the tutorials offered online. I ended up literally copying a template I found online and I still can't get this to work. I have a bunch of files I'll post the main two. Can someone please tell my how to fix this error message? I don't mean to plagiarize, If I can just get this to work, I can work on my own based off a working example.
MainGameFile.as
package {
import com.adobe.serialization.json.JSON;
import com.facebook.graph.Facebook;
import flash.display.Loader;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.IOErrorEvent;
import flash.events.MouseEvent;
import flash.net.URLRequest;
public class FlashMobileWeb extends Sprite {
protected static const APP_ID:String = "647743112027883"; //Your App Id
protected static const APP_URL:String = "https://localhost:3000/";
protected var profilePic:Loader;
public function FlashMobileWeb() {
var accessToken:String;
if (loaderInfo.parameters.accessToken != undefined) {
accessToken = String(loaderInfo.parameters.accessToken); //get
the token passed in index.php
}
Facebook.init(APP_ID, onInit, null, accessToken);
loginBtn.addEventListener(MouseEvent.CLICK, handleLoginClick, false, 0, true);
callBtn.addEventListener(MouseEvent.CLICK, handleCallClick, false, 0, true);
profilePic = new Loader();
profilePic.contentLoaderInfo.addEventListener(Event.INIT, handleProfilePicInit, false, 0, true);
profilePic.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, handleProfilePicIOError, false, 0, true);
profileHolder.addChild(profilePic);
}
protected function onInit(response:Object, fail:Object):void {
if (response) {
outputTxt.appendText("Logged In\n");
loginBtn.label = "Logout";
} else {
outputTxt.appendText("Click to Login\n");
loginBtn.label = "Login";
}
}
protected function handleLoginClick(event:MouseEvent):void {
if (loginBtn.label == "Login") {
var redirectUri:String = APP_URL; //Your App URL as specified in facebook.com/developers app settings
var permissions:Array = ["user_photos", "user_location"];
Facebook.mobileLogin(redirectUri, "touch", permissions);
} else {
outputTxt.appendText("LOGOUT\n");
Facebook.mobileLogout(APP_URL); //Redirect user back to your app url
}
}
protected function onLogout(response:Object):void {
loginBtn.label = "Login";
outputTxt.text = "";
}
protected function handleCallClick(event:MouseEvent):void {
Facebook.api("/me", onApiCall);
}
protected function onApiCall(response:Object, fail:Object):void {
if (response) {
outputTxt.appendText("RESPONSE:\n" + JSON.encode(response) + "\n");
var req:URLRequest = new URLRequest(Facebook.getImageUrl(response.id, "square"));
profilePic.load(req);
profileHolder.nameTxt.text = response.name + "\n";
if (response.location != null) { profileHolder.nameTxt.appendText(response.location.name); }
}
}
protected function handleProfilePicInit(event:Event):void {
profilePic.x = 1;
profilePic.y = profileHolder.height - profilePic.height >> 1;
}
protected function handleProfilePicIOError(event:IOErrorEvent):void {
outputTxt.appendText("Error Loading Profile Pic\n");
}
}
}
AbstractFacebook.as
package com.facebook.graph.core {
import com.facebook.graph.data.FacebookSession;
import com.facebook.graph.net.FacebookRequest;
import flash.net.URLRequestMethod;
import flash.utils.Dictionary;
public class AbstractFacebook {
protected var session:FacebookSession;
protected var openRequests:Dictionary;
public function AbstractFacebook():void {
openRequests = new Dictionary();
}
protected function api(method:String,
callback:Function = null,
params:* = null,
requestMethod:String = 'GET'
):void {
method = (method.indexOf('/') != 0) ? '/'+method : method;
if (session != null) {
if (params == null) { params = {}; }
params.access_token = session.accessToken;
}
var req:FacebookRequest = new FacebookRequest(
FacebookURLDefaults.GRAPH_URL,
requestMethod
);
openRequests[req] = callback;
req.call(method, params, handleRequestLoad);
}
protected function handleRequestLoad(target:FacebookRequest):void {
var resultCallback:Function = openRequests[target];
if (resultCallback === null) {
delete openRequests[target];
}
if (target.success) {
var data:Object = ('data' in target.data) ? target.data.data : target.data;
resultCallback(data, null);
} else {
resultCallback(null, target.data);
}
delete openRequests[target];
}
protected function callRestAPI(methodName:String,
callback:Function = null,
values:* = null,
requestMethod:String = 'GET'
):void {
if (values == null) { values = {}; }
values.format = 'json';
if (session != null) {
values.access_token = session.accessToken;
}
var req:FacebookRequest = new FacebookRequest(
FacebookURLDefaults.API_URL,
requestMethod
);
openRequests[req] = callback;
req.call('/method/' + methodName, values, handleRequestLoad);
}
protected function fqlQuery(query:String, callback:Function):void {
callRestAPI('fql.query', callback, {query:query});
}
protected function deleteObject(method:String, callback:Function = null):void {
var params:Object = {method:'delete'};
api(method, callback, params, URLRequestMethod.POST);
}
protected function getImageUrl(id:String, type:String = null):String {
return FacebookURLDefaults.GRAPH_URL
+ '/'
+ id
+ '/picture'
+ (type != null?'?type=' + type:'');
}
}
}