Dynamic Load Component Not Work In Production - angular6

I am using Angular 6 and I am trying to load component dynamically by it's name
when user click on tab load component by name for this I am using the following code witch is working perfect on build but not work in build --production
loadTabData(tabname: any) {
this.selectedTab = tabname;
var factories = Array.from(this.resolver["_factories"].keys());
var factoryClass = <Type<any>>(
factories.find((x: any) => x.name === tabname)
);
let viewContainerRef = this.comLoad.viewContainerRef;
viewContainerRef.clear();
const factory = this.resolver.resolveComponentFactory(factoryClass);
let componentRef = viewContainerRef.createComponent(factory);
componentRef.instance.serviceId = this.serviceId;
}
when user click on tab I load the related component in production its return the following error
ERROR Error: No component factory found for undefined. Did you add it
to #NgModule.entryComponents?
at Wt (main.b98d71b6b5a909371223.js:1)
at e.resolveComponentFactory (main.b98d71b6b5a909371223.js:1)

Actually, this works fine in development and build since angular compiler not changing the name of component. in this line
var factories = Array.from(this.resolver["_factories"].keys());
var factoryClass = <Type<any>>(
factories.find((x: any) => x.name === tabname)
);
you are searching for component by it's name but in production this name changed you can detect this by print the factories
instead of you can search by component selector like this;
const factories = Array.from(this.resolver["_factories"].values());
const factory: any = factories.find(
(x: any) => x.selector === this.selector
);
selector not changed on productions
Hope this help you

Related

How do I read environment variables in my Appwrite functions?

In the Appwrite console, I'm adding a test environment variable to pass into function...
In my function code (NodeJs) index.js, I'm logging out the value of above variable...
I save the code and use the Appwrite CLI (createTag) to push/publish the code.
Then in Appwrite console, I activate the new function then I execute it and I see this in log...
Clearly I'm missing something but I'm searching the Appwrite docs and I don't see it.
What am I doing incorrectly?
Thank you for helping :-)
Ok looks like as of this post, this is a bug in the Appwrite web UI code. You can do this 2 ways right now. You can set the environment vars in code or you can use the Appwrite CLI. I ended up putting the CLI commend in my NodeJs package.json scripts for quick easy access.
Here are both ways that worked for me...
appwrite functions create --functionId=regions_get_all --name=regions_get_all --execute=[] --runtime=node-16.0 --vars={ 'LT_API_ENDPOINT': 'https://appwrite.league-tracker.com/v1', 'LT_PROJECT_ID': '61eb...7e4ff', 'LT_FUNCTIONS_SECRET': '3b4b478e5a5576c1...ef84ba44e5fc2261cb8a8b3bfee' }
const sdk = require('node-appwrite');
const endpoint = 'https://appwrite.league-tracker.com/v1';
const projectId = '61eb3...7e4ff';
const funcionsSecret = '3b4b478e5a557ab8a...c121ff21977a';
const functionId = process.argv[2];
const name = process.argv[2];
const execute = [];
const runtime = 'node-16.0';
const env_vars = {
"LT_API_ENDPOINT": endpoint,
"LT_PROJECT_ID": projectId,
"LT_FUNCTIONS_SECRET": funcionsSecret
};
// Init SDK
const client = new sdk.Client();
const functions = new sdk.Functions(client);
client
.setEndpoint(endpoint) // Your API Endpoint
.setProject(projectId) // Your project ID
.setKey('33facd6c0d792e...359362efbc35d06bfaa'); // Your secret API key
functions.get(functionId)
.then(
func => {
// Does this function already exist?
if ((typeof (func) == 'object' && func['$id'] == functionId)) {
throw `Function '${functionId}' already exists. Cannot 'create'.\n\n`;
}
// Create the function
functions.create(functionId, name, execute, runtime, env_vars)
.then(
response => console.log(response),
error => console.error(`>>> ERROR! ${error}`)
);
}).catch(
error => console.error(`>>> ERROR! ${error}`)
);
As of Appwrite 0.13.0, an Appwrite Function must expose a function that accepts a request and response. To return data, you would use the response object and either call response.json() or response.send(). The request object has an env object with all function variables. Here is an example NodeJS Function:
module.exports = async (req, res) => {
const payload =
req.payload ||
'No payload provided. Add custom data when executing function.';
const secretKey =
req.env.SECRET_KEY ||
'SECRET_KEY environment variable not found. You can set it in Function settings.';
const randomNumber = Math.random();
const trigger = req.env.APPWRITE_FUNCTION_TRIGGER;
res.json({
message: 'Hello from Appwrite!',
payload,
secretKey,
randomNumber,
trigger,
});
};
In the example above, you can see req.env.SECRET_KEY being referenced. For more information, refer to the Appwrite Functions docs.

fetch the text of my application from the server

I want to change all the static text in my app with a text from a server so I have to fetch this text in LoadingScreen and then export it to use it in other screens
<Text>My products</Text> to <Text>{constants.myProduct}</Text> after import constant from LoadingScreen
How to export the json response from LoadingScreen to all the other Screen ?
there is another approach ?
PS. I don't use Redux
The simplest way, but not the best, is just create and export variable with all text keys. For example:
// text.utils.js
let _textData;
export const loadTextData = () => fetch(YOUR_SERVER)
.then((r) => r.json())
.then(r => _textData = r);
export const getTextData = (key, defaultValue) => _textData[key] || defaultValue;
// init inside App or something else
import {loadTextData} from 'text.utils.js';
componentDidMount() {
loadTextData();
}
// inside components
import {getTextData} from 'text.utils.js';
const myProductText = getTextData('myProduct', 'This is product text');
const myProductCountText = getTextData('myProductCount', 'This is product count text');
<Text>{myProductText}</Text>
<Text>{myProductCountText}</Text>
P.S. It's not a good solution for react. The best choice is create a context or hook, that will provide strings to your components. Also if your string object has nested objects, you may reorganise getTextData function

Why can I access const before declaration in exported module

I'm having this question, since const variables are not hoisted and a syntax error should be thrown.
Why does this code work?
export let testModule = () => {
let test = document.querySelector('.test');
test.innerHTML = myText;
test.style.cssText = 'color: red';
}
const myText = 'IT WORKS!!!!!'
I've attached the working plunk if you want to check for yourself: https://plnkr.co/edit/TR8SvCjQgqPDWpI3?preview
Why can I access const before declaration in exported module
Because testModule() isn't called until later and const myText is defined in a reachable scope by the time the function is called.

How to set a route before a component is created in unit test

I have a component which when created extracts a parameter from url and launches a query.
ngOnInit() {
....
this.id = this.route.snapshot.paramMap.get("my-id");
console.log("will query db for question with id " + this.id);
this.myService.getId(this.id)
}
I want to unit-test the component but I can't figure out how to set the url before TestBed creates this component.
The url should be of format
{
path:'id-details;my-id=:id',// for eg id-details;my-id=1
component:MyComponent
},
I thought I could set the route in beforeEach but that isn't working
beforeEach((done) => {
fixture = TestBed.createComponent(MyComponent);
component = fixture.componentInstance;
let router = TestBed.get(Router);
let location = TestBed.get(Location);
router.navigateByUrl("/id-details;my-id=1");
});
fit('should create', () => {
expect(component).toBeTruthy();
});
In above spec, the component gets created but I don't get id. I tried extracting params in the followinng two ways but I always get null
this.id = this.route.snapshot.paramMap.get("my-id"); //get null
and
this.id = this.route.snapshot.paramMap.get("id-details"); //get null
I also see the following error in the console
context.js:1972 Navigation triggered outside Angular zone, did you forget to call 'ngZone.run()'?
Unhandled Promise rejection: Cannot match any routes. URL Segment: 'question-details;question-id=1' ; Zone: ProxyZone ; Task: Promise.then ; Value: Error: Cannot match any routes. URL Segment: 'question-details;question-id=1'
Try this:
spyOn(component.route.snapshot.paramMap,"get").and.returnValue("some_id")
Or:
let fake_value = "value";
spyOn(component.route.snapshot.paramMap,"get").and.callFake(()=>{
return fake_value;
});
fake_value = "another";
component.someMethod();
expect(...).toBe("another");
fake_value = "then_";
component.someMethod();
expect(...).toBe("then_");

Testing saves data in database

Hi I am trying to run mocha and chai test to test my node js router, which saves a user in mysql database and then returns the same array back.
The problem I am facing at the moment is that I would not like to save the information in the database when I run it from local and when I use a continious integration software like travis/Ci the test fails since there is no database connection. I would like to know how can I test the database saving with the current without actually saving to the database.
Basically meaning having a fake virtual database to save or returning save.
I read that sinon.js can help but I am quite not sure on how to use it.
Here is my code
var expect = require('chai').expect;
var faker = require('faker');
const request = require('supertest');
const should = require('should');
const sinon = require('sinon');
const helper = require('../../models/user');
describe('POST /saveUser',()=>{
it('should save a new user',(done)=>{
var fake =
request(app)
.post('/saveUser')
.send({
Owner : faker.random.number(),
firstname : faker.name.firstName(),
lastname : faker.name.lastName(),
email:faker.internet.email(),
password : faker.random.number(),
token : faker.random.uuid()
})
.expect(200)
.expect((res)=>{
expect(res.body.firstname).to.be.a("string");
expect(res.body.lastname).to.be.a("string");
expect(res.body.Owner).to.be.a("number");
})
.end(done);
});
});
This is the router
router.post('/saveUser',(req,res,next)=>{
saveUser(req.body).then((result)=>{
return res.send(req.body);
}).catch((e)=>{
return res.send('All info not saved');
});
});
And here is the model
saveUser = (userinfo) => new Promise((resolve,reject)=>{
db.query('INSERT INTO user SET ?',userinfo,function(error,results,fields){
if(error){
reject();
}else{
resolve(userinfo);
}
})
});
What you are describing is a stub. With sinon you can stub methods and call fake methods instead like this:
sinon.stub(/* module that implements saveUser */, 'saveUser').callsFake(() => Promise.resolve());