Angular 4: Using Custom RouteReuseStrategy causes Cannot read property 'prototype' of undefined - angular-ui-router

The custom Route reuse strategy is as follows,
import { RouteReuseStrategy,ActivatedRouteSnapshot,DetachedRouteHandler} from '#angular/router';
export class CustomRouteReuseStrategy extends RouteReuseStrategy {
shouldDetach(route: ActivatedRouteSnapshot): boolean { return false; }
store(route: ActivatedRouteSnapshot, detachedTree: DetachedRouteHandle): void {}
shouldAttach(route: ActivatedRouteSnapshot): boolean { return false; }
retrieve(route: ActivatedRouteSnapshot): DetachedRouteHandle { return null ; }
shouldReuseRoute(future: ActivatedRouteSnapshot, curr: ActivatedRouteSnapshot): boolean {
console.log("inside shouldReuseRoute...");
return future.routeConfig === curr.routeConfig ;
}
}
I get this below error
Error: TypeError: Cannot read property 'prototype' of undefined
at __extends (http://localhost:8000/app/UMSClient/com/ipc/ums/modules/shared/CustomRouteReuse.service.js:7:73)
I read through stack overflow posts and couldn't locate a solution. Once this works I want to ensure one of my child component gets reloaded instead of Re-use and then attach component going forward in the project.
I provided in AppModule
{
provide: RouteReuseStrategy,
useClass: CustomRouteReuseStrategy
},
I change extends to implements and the error goes away but the custom route re-use does not work.
i am using angular 4.3.1

The issue was my workspace structure. Angular 2 version was picked up by build wrongly when angular 4 was intended. When I corrected this, it started working fine.

Related

parse-server dotnotation nested subclassing not working

I'm a iOS dev now writing a react app and got an issue with dotnotation when using parse-server with nested subclassing. Value is always undefined even when data is present.
I am using the JS-SDK (Android and iOS SDK works just fine with similar scenario)
Bike class:
import PriceTier from "./PriceTier";
export default class Bike extends Parse.Object {
constructor() {
super("bike");
}
get price_tier(): PriceTier {
return this.get("price_tier");
}
}
Parse.Object.registerSubclass("bike", Bike);
PriceTier Class
export default class PriceTier extends Parse.Object {
constructor() {
super("price_tier");
}
get standard_price(): number {
return this.get("standard_price");
}
}
Parse.Object.registerSubclass("price_tier", PriceTier);
In a part of my app i do a query and want to read the standard_price like this:
const query = new Parse.Query(Bike);
query.include("price_tier");
const bikes = await query.find();
console.log(bikes[0].price_tier.standard_price) // undefined <-- Why is this undefined when i have a getter in subclass
console.log(bikes[0].price_tier.get("standard_price")) // 100 <-- Why does this work but not above?
Above works perfectly fine in both iOS and Android SDK but not the JS-SDK
So what am i missing or what is the JS-SDK missing?

How to build a Model Layer in Vue3 just like other MVC language?

my name is DP, I have 2 years Vue2 experience, but I am new to Vue3. I am learning Vue3 recently, as I found the "setup(Composition API)" just like the "Controller(in MVC)" that I did in other language, so I am trying to build my test Vue3 project in MVC way, but I go some problem can anyone help? thx!
MVC Plan
M - use class
V - use <template> ... </template>
C - use setup
My Problem
working: using loadTopic_inSetup().then() in setup is working, because topicList_inSetup is defined in setup() too.
not working: using loadTopic_inModel() in setup is not working, I guess some kind data keep problem, because in console I can see the data already got from API
as u can see, I am not expert for js/ts, I am a backend developer, so if you know how to do it, plz help thx very much.
BTW, VUE is greet, I love it.
My Code
//APIBased.ts
import { ajax } from "#/lib/eeAxios"
export class APIBased {
//load data with given url and params
loadData(apiPath: string, params?: object): Promise<any> {
apiPath = '/v1/'+apiPath
return ajax.get(apiPath, params)
}
}
//Topic.ts
import { APIBased } from "./APIBased";
import { ref } from 'vue'
export class Topic extends APIBased {
//try keep data in model
topicList: any = ref([]);
constructor() {
super()
}
//direct return ajax.get, let setup do the then+catch
loadTopic_inSetup() {
return super.loadData('topics', { t_type_id: 1 })
}
//run ajax get set return data to this.topicList, keep data in model
loadTopic_inModel() {
super.loadData('topics', { t_type_id: 1 }).then((re) => {
console.log(re.data)
this.topicList = re.data
})
}
}
//EETest.vue
<template>
<EELayoutMainLayout>
<template v-slot:mainContent>
<h1>{{ "Hello Vue3 !!" }}</h1>
<hr/>
{{to.topicList}} //not working... just empty array
<hr/>
{{topicList_inSetup}} //working... topic list return from API show here.
</template>
</EELayoutMainLayout>
</template>
<script lang="ts">
import { defineComponent, getCurrentInstance, ref } from 'vue'
import EELayoutMainLayout from '#/components/eeLayout/EELayoutMainLayout.vue'
import { Topic } from "#/models/Topic";
export default defineComponent({
name: 'EETest',
props: {
},
setup() {
let topicList_inSetup = ref([])
const to = new Topic()
//try keep data in setup, it's working
to.loadTopic_inSetup().then((re) => {
topicList_inSetup.value = re.data
console.log(re.data)
})
//try keep data in model, the function is run, api return get, but data not show, even add ref in model
to.loadTopic_inModel()
return {
topicList,
to,
}
},
components: {
EELayoutMainLayout,
},
})
</script>
A few digressions before solving the problem. Maybe you are a java developer. I personally think it is inappropriate to write the front end with Java ideas. The design of vue3's setup is more inclined to combined functional programming
To fully understand why you need some pre knowledge, Proxy and the get and set method of Object
They correspond to the two core apis in vue, reactive and ref,
The former can only be applied to objects( because proxy can only proxy objects),The latter can be applied to any type(primary for basic javascript types, get and set can apply for any type)
You can modify the code to meet your expectations
loadTopic_inModel() {
super.loadData('topics', { t_type_id: 1 }).then((re) => {
console.log(re.data)
this.topicList.value = re.data
})
}
You cannot modify a ref object directly, a test case to explain what is reactive
when ref function is called, a will be like be wrapped in a class has value properties, and has get and set method
the effect function will call the arrow function, and in this time, the get method of a will be called and it will track as a dependence of the effect function, when a changed, the set method of a will be called, and it will trigger the arrow function,
so when you direct modify the a, the setter method will never trigger, the view will not update
const a = ref(1)
let dummy
let calls = 0
effect(() => {
calls++
dummy = a.value
})
expect(calls).toBe(1)
expect(dummy).toBe(1)
a.value = 2
expect(calls).toBe(2)
expect(dummy).toBe(2)
// same value should not trigger
a.value = 2
expect(calls).toBe(2)

Why is Ionic 3 ion-loader throwing removeView error / not showing when dismiss/present checks in place

I am using an ion-loading component which works fine the first time the view is accessed and the loader is presented and dismissed.
import { AlertController, LoadingController } from 'ionic-angular';
constructor(
public zone: NgZone,
public loadingCtrl: LoadingController,
public alertCtrl: AlertController,
private storage: Storage,
public navCtrl: NavController
) {
this.loading = this.loadingCtrl.create();
}
tryGeolocation() {
this.loading.present();
//misc code
this.markers.push(marker);
this.map.setCenter(pos);
//if(this.loading){
this.loading.dismiss();
}
However when I navigate back to the view and the loader is again presented I get a error:
Error: Uncaught (in promise): removeView was not found
I have tried to followe the advice here and introduced checks to see if loader has been dismissed but now the loader never comes into view:
if (this.loading == null){
console.log("Map.ts: Presenting loader.");
this.loading.present();
}
if (this.loading != null){
console.log("Map.ts: Dismissing loader.");
this.loading.dismiss();
}
I am using ionic 3.9.9, angular 5.2.11
Any input appreciated.
Seems to be allot of different solutions out there depending on the context, for me the solution was to move the loader create call from the module constructor to the method calling present and dismiss:
tryGeolocation() {...
this.loading = this.loadingCtrl.create();
this.loading.present();
//some code
this.loading.dismiss();
}

Guideline for memoized selectors in state base class

I have a question regarding NGXS Store and the usage of memoized #Selector()s in a state class hierarchy.
What would be the recommended approach to the issue described below?
The NGXS Store documentation does not provide a guideline/recommendation in this regard.
Given this sample state setup,
export interface BaseModel { data: string[]; }
// base class not a state!
export class BaseState {
#Selector()
static dataSelect(state: BaseModel) { return state.data; }
// ...
}
export interface DerivedModel extends BaseModel {}
#State<DerivedModel>({ name: 'derived'; })
export class DerivedState extends BaseState {
// ...
}
export interface UsingModel { thing: number; }
#State<UsingModel>({ name: 'using'; })
export class UsingState implements NgxsOnInit {
constructor(private _store: Store) {}
ngxsOnInit(ctx: StateContext<UsingModel>) {
// have this state update when derived state changes
this._store.select(DerivedState.dataSelect).subscribe(data => console.log(data));
}
// ...
}
When letting this piece of code run it will print out undefined because the state argument
of the dataSelect(...) method will not be set.
I tracked the cause to BaseState not being a NGXS State and therefore missing an internal NGXS_META
property which in turn causes the undefined argument.
Adding BaseState to the selector (such as #Selector([BaseState])) to force the state to still be
included also does not have the desired effect, because now NGXS cannot navigate to a matching state slice.
I found two ways to make this work as desired:
1. duplicate the #Selector(...) method in every derived state implementation. This though defeats the reasons why the state class hierarchy was originally designed.
2. use something like #DerivedSelector(...) that works according to the standard decorator but dynamically creates selectors on use for each of the encountered derived state classes.
Thank you.
As far as I know this can not be achived using the #Selector annotation, but with createSelector().
export class BaseState {
static dataSelect() {
return createSelector(
[this],
(state: BaseModel) => {
return state.data;
}
);
}
//...
}
If you change your base state like this, your code will work. For details refer to the NGXS docs

Angular Dart component events

I am trying to pass custom events from a component to its parent component/controller
confirm.html
<div class="comfirm-component">
<content></content>
Yes
No
</div>
confirm.dart
#Component(
selector: "confirm-component",
templateUrl: 'confirm.html',
useShadowDom: false,
publishAs: "ctrl"
)
class ConfirmComponent {
void yes(){
print('yes');
// Fire confirm-yes event
}
void no(){
print('no');
// Fire confirm-no event
}
}
is there something like this?:
<confirm-component on-confirm-yes="doSomething()" on-confirm-no="doSomethingElse()">
Do you want to delete
</confirm-component>
I could use a normal StreamController but then i'd had to connect my components with code.
confirmComponent.onConfirmYes.listen()
confirmComponent.onConfirmNo.listen()
I also found this:
How to communicate between Angular DART controllers
And this:
angulardart components - dispatch custom event
In both treads scope.emit is mentioned. But i didn't find a way to use it with a component instead of a controller. Is there a full example vor angular.dart v0.14.0?
Is scope.emit the thing i'm searching for?
This should be the same, just add a scope argument to the constructor so the component gets the scope injected.
There was a related change in Angular 0.14.0 https://github.com/angular/angular.dart/commit/181f01448555c475869505491159045904e5dc89
I haven't yet tried this.
From the description you need to implement ScopeAware
#Component(...)
class MyComponent implements ScopeAware {
Watch watch;
MyComponent(Dependency myDep) {
// It is an error to add a Scope / RootScope argument to the ctor and will result in a DI
// circular dependency error - the scope is never accessible in the class constructor
}
void set scope(Scope scope) {
// with this scope you should be able to use emit
// This setter gets called to initialize the scope
watch = scope.rootScope.watch("expression", (v, p) => ...);
}
}
Based on the answer from Günter i built this working example:
#Component(
selector: "confirm-component",
templateUrl: 'component/confirm.html',
useShadowDom: false,
publishAs: "ctrl"
)
class ConfirmComponent implements ScopeAware {
Scope scope;
void yes(){
scope.emit('confirm', 'yes');
}
void no(){
scope.emit('confirm', 'no');
}
}
#Component(
selector: "my-component",
templateUrl: 'component/my.html',
useShadowDom: false,
publishAs: "ctrl"
)
class MyComponent implements ScopeAware{
void set scope(Scope scope) {
Stream mystream = scope.on('confirm');
mystream.listen((event){
print('confirmed: ' + event.data);
});
}
}

Resources