I'm encountering the error
ContestDetailsModalComponent.html:21 ERROR TypeError: Cannot assign to read only property 'winner' of object '[object Object]'
at ContestDetailsModalComponent.onWinner (contest-details-modal.component.ts:88:24)
at Object.eval [as handleEvent] (ContestDetailsModalComponent.html:21:17)
at handleEvent (core.js:43993:77)
at callWithDebugContext (core.js:45632:1)
at Object.debugHandleEvent [as handleEvent] (core.js:45247:1)
at dispatchEvent (core.js:29804:1)
at core.js:42925:1
at HTMLButtonElement.<anonymous> (platform-browser.js:2668:1)
at ZoneDelegate.invokeTask (zone-evergreen.js:399:1)
at Object.onInvokeTask (core.js:39680:1)
when I try to make the assignment
this.contest.winner = winnerId;
you see in the following code snippet:
public onWinner(winnerId: number): void {
const post: Post = new Post();
post.title = `The winner of the contest has been elected: ${this.contest.title}`;
post.description = `Tizio has been elected winner of the contest and ${this.user.name} gives him the most welcome compliments`;
post.user = this.user;
post.contest = this.contest;
post.type = Type.WINNER;
post.level = Level.SUCCESS;
this.contest.winner = winnerId;
this.store.dispatch(PostActions.savePost({post}));
this.store.dispatch(ContestActions.saveContest({contest: this.contest}));
}
I've done this kind of assignment with other classes around the project and they never bothered me.
I enclose the contest class and post if it is useful:
export class Contest {
public id: number;
public title: string;
public description: string;
public rules: string;
public startDate: Date;
public endDate: Date;
public status: Status;
public winner: number;
public bannedUser: number[];
}
export class Post {
public id: number;
public title: string;
public description: string;
public level: Level;
public type: Type;
public user: User;
public publishDate: Date;
public contest: Contest;
}
I also tried some solutions always found on this forum such as:
Object.assign(target, source);
But he rightly tells me that this.contest.winner is null or undefined.
I hope for your help. Thank you
Edit:
This is the entire component.ts where onWinner() is present.
#Component({
selector: 'app-contest-details-modal',
templateUrl: './contest-details-modal.component.html',
styleUrls: ['./contest-details-modal.component.scss'],
})
export class ContestDetailsModalComponent implements OnInit, OnDestroy, AfterViewChecked {
private readonly subscriptions: Subscription = new Subscription();
public id: number;
public user: User;
public contest: Contest;
public images: Image[];
public hasVoted: boolean;
constructor(
private readonly bsModalRef: BsModalRef,
private readonly modalService: BsModalService,
private readonly store: Store<AppState>,
private cdRef: ChangeDetectorRef
) { }
public ngOnInit(): void {
this.subscriptions.add(this.store.pipe(select(AuthSelectors.getUser)).subscribe((user: User) => {
if (user) {
this.user = user;
}
}));
this.subscriptions.add(this.store.pipe(select(ContestSelectors.getById)).subscribe((contest: Contest) => {
if (contest) {
this.contest = contest;
}
}));
this.subscriptions.add(this.store.pipe(select(ImageSelectors.getImages)).subscribe((images: Image[]) => {
if (images.length) {
this.images = images;
}
}));
this.subscriptions.add(this.store.pipe(select(UserSelectors.check)).subscribe((ack: Ack) => {
if (ack) {
this.store.dispatch(AuthActions.updatedUser({userId: this.user.id}));
this.modalService.show(UploadImageModalComponent);
this.bsModalRef.hide();
}
}));
this.subscriptions.add(this.store.pipe(select(ImageSelectors.check)).subscribe((ack: Ack) => {
if (ack) {
this.bsModalRef.hide();
}
}));
}
public ngOnDestroy(): void {
this.store.dispatch(UserActions.clean());
this.store.dispatch(ContestActions.clean());
this.subscriptions.unsubscribe();
}
public onWinner(winnerId: number): void {
const post: Post = new Post();
post.title = `The winner of the contest has been elected: ${this.contest.title}`;
post.description = `Tizio has been elected winner of the contest and ${this.user.name} gives him the most welcome compliments`;
post.user = this.user;
post.contest = this.contest;
post.type = Type.WINNER;
post.level = Level.SUCCESS;
this.contest.winner = winnerId;
this.store.dispatch(PostActions.savePost({post}));
this.store.dispatch(ContestActions.saveContest({contest: this.contest}));
}
public onJoin(): void {
this.store.dispatch(UserActions.saveUser({idUser: this.user.id, id: this.contest.id}));
}
public onVote(image: Image): void {
let vote: number = image.vote;
vote = vote + 1;
this.store.dispatch(ImageActions.updateImage({photoId: image.id, votes: vote, userId: this.user.id}));
this.store.dispatch(AuthActions.updatedUser({userId: this.user.id}));
}
public isContain(contestId: number): boolean {
if (this.user.myContest) {
for (const i of this.user.myContest) {
if (contestId === i) {
return true;
}
}
}
return false;
}
public isImageVoted(id: number): boolean {
if (this.user.favouritePhoto) {
for (const imageVoted of this.user.favouritePhoto) {
if (id === imageVoted) {
this.hasVoted = true;
return true;
}
}
return false;
}
}
public onBan(image: Image): void {
this.modalService.show(BanModalComponent, {initialState : image});
this.bsModalRef.hide();
}
public isBan(contestId: number): boolean {
if (this.user.whereBanned) {
for (const contestBanned of this.user.whereBanned) {
if (contestId === contestBanned) {
return true;
}
}
return false;
}
}
public ngAfterViewChecked(): void {
this.cdRef.detectChanges();
}
}
contest contains a reference to an Observable emission, and all references emitted by Observables are readonly. Either clone contest:
this.contest = { ...contest };
Or, better, leave it as an Observable and consume it as such, generally via the async pipe. Also, if you're using NgRx, you want to be using store.select():
this.contest$ = this.store.select(ContestSelectors.getById);
Related
How I can use getter and setter in TypeORM.
I saw issues in here and also here, but not found answer
For example a left my User entity
export class User {
#PrimaryGeneratedColumn()
private id: number;
#Column()
#Length(4, 20)
#IsNotEmpty()
private name: string;
#Column()
#Length(4, 100)
#IsNotEmpty()
private password: string;
public getId(): number {
return this.id;
}
public getPassword(password: string): string {
return this.password;
}
public setPassword(password: string): User {
this.password = bcrypt.hashSync(password, 8);
return this;
}
public setName(name: string): User {
this.name = name;
return this;
}
}
I use TypeORM version 0.2.7
#BeforeInsert & #AfterLoad
BeforeInsert https://typeorm.io/#/listeners-and-subscribers/beforeinsert
AfterLoad https://typeorm.io/#/listeners-and-subscribers/afterload
Use #BeforeInsert as setter
#Entity()
export class Post {
#BeforeInsert()
updateDates() {
this.createdDate = new Date()
}
}
Use #AfterLoad as getter
#Entity()
export class Post {
#AfterInsert()
resetCounters() {
this.counters = 0
}
}
I try to select boxes for participants. So that a user will been able to sent some data to one or more participant. And after the user selected some participants the user will be redirected to a Model dialog from anuglar material.
So I have this:
export class EcheqSelectorComponent implements OnInit, OnDestroy {
private subscriptions = new Subscription();
echeqs: EcheqFamilyInfo[] = [];
allEcheqs: EcheqFamilyInfo[] = [];
echeqFamily: EcheqFamilyInfo;
searchInput = '';
filtering = false;
participantInfo: ParticipantInfoDTO;
echeqsToSend: EcheqFamilyInfo[] = [];
echeqSubmissionBatchDTO: EcheqSubmissionBatchDTO;
participantIds$: Observable<string[]>;
patientId: string;
public participantIds: string[] = [];
public participantIdsFromRoute: string[] = [];
constructor(
private apiService: EcheqDefinitionService,
private dialog: MatDialogRef<EcheqSelectorComponent>,
public selectedParticipantService: SelectedParticipantsService,
private submissionService: EcheqSubmissionMedicalService,
private snackBar: MatSnackBar,
#Inject(MAT_DIALOG_DATA) public data: any,
public dialogRef: MatDialogRef<EcheqSelectorComponent>
) {
this.participantInfo = data.participant;
this.participantIdsFromRoute = this.data.participant.participantId ? [this.data.participant.participantId] : undefined;
}
ngOnInit() {
this.subscriptions.add(
this.apiService.listEcheqFamilies().subscribe(families => {
this.echeqs = families;
this.allEcheqs = families;
})
);
}
And the matdialog service looks like this:
export class DialogModelService {
participant: ParticipantInfoDTO;
constructor(private dialog: MatDialog, route: ActivatedRoute) {
this.participant = route.snapshot.data['participant'];
console.log('Route:', this.participant);
}
openEcheqSelectorDialog(participant: ParticipantInfoDTO): Observable<any> {
const dialogRef = this.dialog.open(EcheqSelectorComponent, {
width: '600px',
maxHeight: 'calc(100vh - 2em)',
data: {
participant: participant
}
});
return dialogRef.afterClosed();
}
openSchemaSelectorDialog(participantId: string): Observable<any> {
const dialogRef = this.dialog.open(SchemaSendDialogComponent, {
width: '600px',
maxHeight: 'calc(100vh - 2em)',
data: {
participant: participantId
}
});
return dialogRef.afterClosed();
}
}
But after I select some participants and trigger the event sent, then I get an error on this line:
this.participantIdsFromRoute = this.data.participant.participantId ? [this.data.participant.participantId] : undefined;
}
saying:
EcheqSelectorComponent_Host.ngfactory.js? [sm]:1 ERROR TypeError: Cannot read property 'participantId' of undefined
at new EcheqSelectorComponent (echeq-selector.component.ts:50)
at createClass (core.js:18681)
at createDirectiveInstance (core.js:18550)
at createViewNodes (core.js:19776)
at createRootView (core.js:19690)
at callWithDebugContext (core.js:20722)
at Object.debugCreateRootView [as createRootView] (core.js:20208)
at ComponentFactory_.push../node_modules/#angular/core/fesm5/core.js.ComponentFactory_.create (core.js:18029)
at ComponentFactoryBoundToModule.push../node_modules/#angular/core/fesm5/core.js.ComponentFactoryBoundToModule.create (core.js:7812)
at ViewContainerRef_.push../node_modules/#angular/core/fesm5/core.js.ViewContainerRef_.createComponent (core.js:18140)
So what I have to do to fix this?
Thank you
I have a problem and very strange behavior with autofill in Chrome. When I login and then logout from app, input fields (email, password) were autocompleted but fields looks like they are frozen and not clickable.
This bug is not every time reproduced, it happens in 1/10 cases.
I noticed on logout when fields get autocompleted, after 1 seconds font gets smaller in inputs and after that if you click on input there it seems like you are not clicking , nothing happens, but if you type some text (numbers not work, stays like frozen) input field goes as normal.
Here is gif with strange behavior:
https://gifyu.com/image/kTkX
I tried to set autocomplete="off" , but not working.
Also I matched all css clases in input fields to see is there some overriding css, but everything looks good.
<form [formGroup]="loginForm">
<input id="emailHeader" type="text" formControlName="email" placeholder="E-mail">
<input #password type="password" formControlName="password" placeholder="Lozinka">
<input type="submit" (click)="executeLogin()" value="Prijava">
</form>
I expect to fields not been frozen after autofill.
public loginForm: FormGroup;
public emailInput: ElementRef;
public passwordInput: ElementRef;
#ViewChild('email') set emailContent(content: ElementRef) {
this.emailInput = content;
}
#ViewChild('password') set passwordContent(content: ElementRef) {
this.passwordInput = content;
}
// UI helpers
public showLoginForm: boolean;
public showBalance: boolean;
public player: PlayerModel = new PlayerModel({});
public balanceInfo: BalanceInfoModel = new BalanceInfoModel({});
public nxcsBalanceInfo: NXCSBalanceInfoModel = new NXCSBalanceInfoModel({});
public dialogType = DialogType;
public customMessageError = '';
// Store
private headerState$: Observable<any>;
private loginState$: Observable<any>;
private playerState$: Observable<any>;
private emailInput$: Observable<any>;
private passwordInput$: Observable<any>;
private balanceState$: Observable<any>;
private headerSubscription: Subscription;
private loginSubscription: Subscription;
private playerSubscription: Subscription;
private emailSubscription: Subscription;
private passwordSubscription: Subscription;
private balanceSubscription: Subscription;
// tslint:disable-next-line:no-inferrable-types
private leftMenu: string = '';
// tslint:disable-next-line:no-inferrable-types
private rightMenu: string = '';
constructor(
private authService: AuthService,
private fb: FormBuilder,
private store: Store<any>,
private route: Router,
private localStorageService: LocalStorageService,
private playerService: PlayerService,
private notificationService: NotificationService,
private dialogService: DialogService,
private helpers: HelpersService,
private translateCode: TranslateCode,
private promotionService: PromotionService,
) {
this.loginForm = this.buildLoginForm();
}
ngOnInit() {
this.setupStore();
}
ngAfterViewInit() {
this.formEventsAfterViewInit();
}
ngOnDestroy() {
this.headerSubscription.unsubscribe();
this.loginSubscription.unsubscribe();
this.playerSubscription.unsubscribe();
this.notificationService.closeConnection();
}
public executeLogin() {
if(!this.loginForm.valid) {
this.customMessageError = this.translateCode.transform("EMPTY_INPUT_MESSAGE");
return;
}
this.authService.login(new LoginModel({...this.loginForm.value, details: this.helpers.sendSessionData()}))
.subscribe(
data => {
this.localStorageService.setUserAfterLogin(data.token);
this.customMessageError = '';
this.loginForm.reset();
this.route.navigate(['/app/casino']);
},
error => {
error.message.includes('Račun je zaključan') ? this.store.dispatch(new PopupNotification(error.message)) : this.customMessageError = error.message
this.addAfterErrorSubscription();
}
);
}
public openDialog(dialogType: string): void {
switch (dialogType) {
case DialogType.PAYMENT:
this.openWithdrawalDialog()
break;
case DialogType.PAYMENT_DEPOSIT:
this.checkRegistrationStep();
break;
case DialogType.TRANSACTION_HISTORY:
this.store.dispatch(new OpenDialog({
type: dialogType,
}));
break;
}
}
public openInternalTransactionsDialog(): void {
this.promotionService.getPromotionsByLocation('NXCS_DEPOSIT')
.subscribe(
data => this.dialogService.openDialog(MENU_DIALOGS.INTERNAL_TRANSACTION, { promotions: data }),
error => this.dialogService.openDialog(MENU_DIALOGS.INTERNAL_TRANSACTION, { promotions: []}),
);
}
public backToRegistrationStep() : void {
switch (this.player.registrationStep) {
case 1 : this.route.navigate(['/auth/registration/step-two']);
break;
case 2 : this.route.navigate(['/auth/registration/step-three']);
break;
case 3 : this.route.navigate(['/auth/registration/step-four']);
break;
case 4 : this.route.navigate(['/auth/registration/step-five']);
break;
case 5 : this.route.navigate(['/auth/registration/step-six']);
break;
default : this.route.navigate(['/login']);
break;
}
}
public toggleMenu(dialog): void {
if (dialog === 'left') {
this.leftMenu = this.leftMenu === dialog ? '' : dialog;
}
if (dialog === 'right') {
this.rightMenu = this.rightMenu === dialog ? '' : dialog;
}
this.dispatchShadow();
}
private openWithdrawalDialog(_data: any = {}): void {
const playerRole = this.localStorageService.getPlayer()['profileRole'];
if (playerRole === 'WITHDRAWAL_DISABLED' && this.player.uploadedAdditionalInfo) {
this.store.dispatch(new OpenNotification({ type: NotificationType.WITHDRAWAL_DISABLED }));
return;
}
playerRole === 'WITHDRAWAL_DISABLED' ?
this.store.dispatch(new OpenNotification({type: NotificationType.MONEY_LAUNDERING})) :
this.dialogService.openDialog(MENU_DIALOGS.WHITDRAWALS, _data);
}
private openProceedToRegistration(): void {
this.store.dispatch(new OpenNotification ({type: NotificationType.PROCEED_REGISTRATION}))
}
private checkRegistrationStep(): void {
if(this.player.registrationStep < 6) {
this.openProceedToRegistration();
} else {
this.dialogService.openDialog(MENU_DIALOGS.DEPOSITS, {});
}
}
private dispatchShadow(): void {
if (this.leftMenu !== '') {
this.store.dispatch(new OpenedLeftMenu());
this.leftMenu = '';
}
if (this.rightMenu !== '') {
this.store.dispatch(new OpenedRightMenu());
this.rightMenu = '';
}
}
private buildLoginForm(): FormGroup {
return this.fb.group({
email: [
'', Validators.compose([Validators.required, Validators.min(5)]),
],
password: [
'', Validators.compose([Validators.required, Validators.min(5)])
],
});
}
private loadBalance(): void {
this.playerService.getPlayerBalance().toPromise()
.then(data => this.store.dispatch(new SetPlayerBalance({balanceInfo: new BalanceInfoModel(data) })))
.then(() => {
if (this.player.externalId) {
this.playerService.getNXCSPlayerBalance()
.subscribe(
data => this.store.dispatch(new SetPlayerNXCSBalance({ nxcsBalanceInfo: new NXCSBalanceInfoModel(data) })),
error => console.log(error),
);
}
});
}
// Store methods
private setupStore(): void {
this.headerState$ = this.store.pipe(select('headerStore'));
this.loginState$ = this.store.pipe(select('loginStore'));
this.playerState$ = this.store.pipe(select('playerStore'));
this.balanceState$ = this.store.pipe(select('balanceStore'));
this.addSubscriptions();
}
private formEventsAfterViewInit(): void {
if (this.emailInput && this.passwordInput) {
this.emailInput$ = fromEvent(this.emailInput.nativeElement, 'focus');
this.passwordInput$ = fromEvent(this.passwordInput.nativeElement, 'focus');
this.addFormEventsSubscriptions();
}
}
private addFormEventsSubscriptions(): void {
this.emailSubscription = this.emailInput$.subscribe(() => this.triggerEmailFocus());
this.passwordSubscription = this.passwordInput$.subscribe(() => this.triggerPasswordFocus());
}
private triggerEmailFocus(): void {
this.emailInput.nativeElement.select();
if (this.emailSubscription) {
this.emailSubscription.unsubscribe();
}
}
private triggerPasswordFocus(): void {
this.passwordInput.nativeElement.select();
if (this.passwordSubscription) {
this.passwordSubscription.unsubscribe();
}
}
private addSubscriptions(): void {
this.addHeaderSubscription();
this.addLoginSubscription();
this.addPlayerSubscription();
this.setBalanceSubscription();
}
private addHeaderSubscription(): void {
this.headerSubscription = this.headerState$
.subscribe(headerState => this.showLoginForm = headerState !== HeaderActionTypes.LoginPage);
}
private addLoginSubscription(): void {
this.loginSubscription = this.loginState$
.subscribe(loginState => {
if (loginState) {
this.loadBalance();
this.notificationService.connect(localStorage.getItem('token'));
} else {
this.notificationService.closeConnection();
}
this.showBalance = loginState;
this.formEventsAfterViewInit();
});
}
private addPlayerSubscription(): void {
this.playerSubscription = this.playerState$
.subscribe(playerData => this.player = playerData);
}
private addAfterErrorSubscription(): void {
this.passwordSubscription = this.passwordInput$.subscribe(() => {
if (this.customMessageError !== '') {
this.customMessageError = '';
this.passwordSubscription.unsubscribe();
}
});
}
}
I was facing the same issue in Angular and found a workaround for this scenario, resetting the input field's value on input click seems to fix the locking issue for me.
HTML:
<input (click)="unfreezeInput($event)">
TS:
unfreezeInput(el) {
// setting input value again makes it editable
el.target.value = el.target.value;
}
This is an issue that happens every time Google Chrome autofills the fields when you permit it to save your login credentials on any form. It bugged me out the first times as well.
I tried giving it a shot or two back when I encountered it for the first, but I gradually moved on and accepted it as a not-a-big deal kinda bug that every chrome user gotta have to deal with.
So in conclusion, it's got nothing to do with your code. If you want to unfreeze the input fields, start typing something in them to change their value.
I hope, this helps you and your nerves in accepting this browser-related behavior.
Have you tried using the a href tag? I know it's an obvious thing, but sometimes we forget to do things like that. Also, you can use the a:hover tag in your CSS.
i need a bit of help.
I am trying to display data from specific loged in user but i have a hard time.
in html :
<div *ngFor="let to of UnData">
TS:
export class something {
todo: AngularFireList<any>;
UnData = [];
userId: string;
constructor(public navCtrl: NavController, public navParams: NavParams, private db: AngularFireDatabase, private fire: AngularFireAuth) {
this.fire.authState.subscribe(user =>{
if(user) this.userId = user.uid
});
if (!this.userId) return;
this.db.list("people/${this.userId}").valueChanges().subscribe(_data => {
this.UnData = _data;
console.log(this.UnData);
});
}
console.log gives me nothing in return. I think i am doing something wrong in code where i am getting data from database. Please give me a bit of help :-)
Thanks Frank,
the first problem was backticks but i still had problems and solved and important part was ngOnInit(userId:string):
export class something {
todo: AngularFireList<any>;
unData = [];
userId: string;
title: string;
desc: string;
constructor(public navCtrl: NavController, public navParams: NavParams, private db: AngularFireDatabase, private fire: AngularFireAuth) {
this.fire.authState.subscribe(user => {
if (user) {
this.userId = user.uid;
console.log(this.userId);
}
});
}
postDatatoDB(title: string, desc: string, userId: string): void {
this.db.list("/tasks/" + this.userId).push({ title: title, desc: desc });
this.title = '';
this.desc = '';
}
**ngOnInit(userId:string)** {
this.db.list<any>(`/tasks/${this.userId}`).valueChanges().subscribe(data => {
this.unData = data;
console.log(this.unData);
});
}
}
I'm new in TypeScript.
I'm getting error when trying to instantiating the class.
Below is my sample code, actual code is different can't share.
module ABC {
export class A {
public execute<T>(action: string, data?: any, callerContext?: any): IAsyncResult<T> {
// CODE::
var requestMessage = new Common.ClientClasses.ClientRequestMessage(); **// **ERROR- "WinRTError: Class not registered"****
requestMessage.requestUri = actionRequest;
requestMessage.method = "POST";
requestMessage.body = data ? JSON.stringify(data, null, 2) : null;
Common.ClientClasses.ClientRequest.executeAsync(requestMessage)
.done((result: Common.ClientClasses.ClientResponeMessage) => {
// CODE:
}
// Code::
}
}
}
declare module Common.ClientClasses {
class ClientRequestMessage {
public requestUri: string;
public method: string;
public body: string;
}
class ClientResponeMessage {
public status: number;
public statusText: string;
public responseText: string;
}
class ClientRequest {
static executeAsync(clientRequestMessage: ClientRequestMessage): any;
}
}
I did some improvements, should work:
module ABC {
export class A {
public execute<T>(action: string, data?: any, callerContext?: any) {
var requestMessage = new Common.ClientClasses.ClientRequestMessage();
requestMessage.method = "POST";
requestMessage.body = data ? JSON.stringify(data, null, 2) : null;
Common.ClientClasses.ClientRequest.executeAsync(requestMessage)
}
}
}
module Common.ClientClasses {
export class ClientRequestMessage {
public requestUri: string;
public method: string;
public body: string;
}
class ClientResponeMessage {
public status: number;
public statusText: string;
public responseText: string;
}
export class ClientRequest {
static executeAsync(clientRequestMessage: ClientRequestMessage): any {
console.log("test");
}
}
}
Then it can be run as following:
var a = new ABC.A();
a.execute("some string");
declare module creates a definition file used for Intellisense but it doesn't provide any implementation that's why I changed your code so this fragment can work.
Also if you want to use any classes from the module, you must export them so they can be visible from outside of that module.