Angular 8 baseUrl gets wiped out - javascript

What we try to do is integrate and angular app in a PHP environment.
So the site will completely run on PHP for the static context, only when the user clicks on login, the will end up in the angular part.
So, now the problem.
When we enter the URL in PHP, it will be something like ...domain/nl/page.
So far so good, and this get redirected to angular, also this works, angular load.
But then angular deletes the last part of the link and changes it to
...domain/{pageThatAngularIsIn}.
This is where we want to keep the language en the URL should be
.../domain/nl/{pageThatAngularIsIn} or even
.../domain/nl/page/{pageThatAngularIsIn} -> step by step
So angular should ignore the language part in the URL but also not wipe it form the URL.
Anybody know if this is possible of why this happens?

Your problem is probably happening because Angular thinks that domain/ is the base route on which it should append its own routing. From your description, it sounds like you wan the base route to be domain/nl/ instead.
This is a simple fix. In the index.html file that has your angular root component embedded, look for a base element in the head and set it to the base path. By default, it's usually something like this:
<base href="/">
Experiment with it to get what you need. Perhaps:
<base href="/nl">
See the docs
If you will need to use that same base within your angular app, for instance to make http calls in a way that will use the same base, you should probably use the APP_BASE_HREF in your root module providers instead. Like:
import {Component, NgModule} from '#angular/core';
import {APP_BASE_HREF} from '#angular/common';
#NgModule({
...
providers: [{provide: APP_BASE_HREF, useValue: '/nl'}]
})
class AppModule {}
With this you will be able to inject the base in your services, for example to make your http calls.
#Injectable()
export class MyService {
constructor(
private http: HttpClient,
#Inject(APP_BASE_HREF) private baseHref: string
) {}
getRecords() {
return this.http.get(this.baseHref + '/records')
}
}
See the docs

Related

How to use new instance for every new HTTP request in NestJS?

I have an API and was trying to send a request. That is working but I noticed that the classes were not destroyed after I received a response. I'm working with nestJS at the moment but nodeJS + expressJS also had this issue when I tried to test.
I'm using following code:
#Injectable()
export class UsersService {
s = '';
constructor() {}
async findAll(): Promise<any> {
this.s += ' haha ';
return await this.s;
}
}
This returned haha first time haha haha the second time and so on.
I'm not really sure if this is the desired behaviour or may have not configured properly, because I'm just learning nestJS now. I have previously worked with Zend Framework which did not show this behaviour.
Any guidance will be much appreciated.
Thank you.
With the release of nest.js 6.0, injection scopes were added. With this, you can choose one of the following three scopes for your providers:
SINGLETON: Default behavior. One instance of your provider is used for the whole application
TRANSIENT: A dedicated instance of your provider is created for every provider that injects it.
REQUEST: For each request, a new provider is created. Caution: This behavior will bubble up in your dependency chain. Example: If UsersController (Singleton) injects UsersService (Singleton) that injects OtherService (Request), then both UsersController and UsersService will automatically become request-scoped.
Usage
Either add it to the #Injectable() decorator:
#Injectable({ scope: Scope.REQUEST })
export class UsersService {}
Or set it for custom providers in your module definition:
{
provide: 'CACHE_MANAGER',
useClass: CacheManager,
scope: Scope.TRANSIENT,
}
What you are looking for are request-scoped providers. They are not supported in nest v5, see this issue. As for now, all providers are singletons.
They were added with this pull request though and will be part of nest v6. With the new version, we will get transient and per-request scopes.

how to access DOM elements in angular 4 service?

I am able to access DOM elements components like below
declare var jQuery: any;
declare var $: any;
//component stuff
$('.my_class').innerHeight();
I am trying to implement the same inside the service class, but dom elements and template is not accessible in the service class.
p.s: this is not duplicate of how to access them in components.
You can access DOM from an Angular service using the plain javascript document object, with some little additions to your service:
// We import not only "Injectable", but "Inject" too, from #angular/core
import { Injectable, Inject } from '#angular/core';
// We import DOCUMENT from #angular/common. Be careful, because the old import from '#angular/platform-browser' is deprecated.
import { DOCUMENT } from '#angular/common';
// Our standard service class in the usual way
#Injectable()
export class LoadingSpinnerService {
// In the constructor we inject a dependency to DOCUMENT, of type HTMLDocument
constructor(#Inject(DOCUMENT) private document: HTMLDocument) {
// We create a new div in the DOM, child of the body tag, <div id="LoadingSpinner"></div>
var NewDomElement = this.document.createElement("div");
NewDomElement.setAttribute("id", "LoadingSpinner");
document.body.appendChild(NewDomElement);
}
}
As you will probably know, you crete the service from the command line with something like:
ng g s loading-spinner
Don't forget to edit the app.module.ts to add the "import" to the service, and the item to the "providers" array in its "#NgModule" decorator:
import { LoadingSpinnerService } from './WHATEVER-DIRECTORY-YOU-CREATE-THE-SERVICE/loading-spinner.service';
(...)
providers: [LoadingSpinnerService,
(...)
About the topic of using angular services only for data, i don't agree. As you can read in the official architecture guide for services:
https://angular.io/guide/architecture-services
Service is a broad category encompassing any value, function, or feature that an app needs.
A component can delegate certain tasks to services, such as fetching data from the server, validating user input, or logging directly to the console.
The provided example just in this documentation is for a log data service.
Hope this helps someone.
You can't in services. You can do it javascript way like document.getElementById.
In components and directives You can use ViewChild from #angular/core
HTML:
<div class="my_class" #myElement></div>
TS:
import { ElementRef, ViewChild } from '#angular/core';
#ViewChild('myElement') myElement:ElementRef;
console.log(this.myElement.nativeElement.offsetHeight); // inside any function.
I guess you cannot directly access with CSS selectors by Angular way. Alternatively, you can just use plain old JavaScript
document.getElementsByClassName("my-class");
Note: You can only do this in components and directives not inside services
Why Services
Components shouldn't fetch or save data directly and they certainly shouldn't knowingly present fake data. They should focus on presenting data and delegate data access to a service.
Source: https://angular.io/tutorial/toh-pt4
In Simpler terms:
component, directive for presenting, manipulating and interacting with DOM
services are for data handling between your component and backend

How to access external javascript file from angular 2 component

I am very new to angular and front end web development, so maybe i am missing something
basic but i did not succeed to search a solution for that issue.
according to that answer: Call pure javascript function from Angular 2 component
and following that example
I am trying to import external .js file to my angular component:
import '../../../src/Plugin/codemirror/mode/custom/custom.js'
#Component({
selector: 'txt-zone',
templateUrl: 'app/txtzone/Txtzone.component.html',
styleUrls: ['app/txtzone/TxtZone.css'],
})
the path is the correct relative path, i know that because if it loads diractly from the url text box via the browser [http://localhost:50371/src/Plugin/codemirror/mode/custom/custom.js]
i can see the file content...
this is the exception that the chrome debugger is throwing:
zone.js:2263 GET
http://localhost:50371/src/Plugin/codemirror/lib/codemirror 404 (Not
Found)
as you can see the path was changed (don`t understand why?)
1. how can i solve this issue?
2. why the path of the .js file is not the referenced path?
3. maybe there is a better way to load external .js file into my component?
it looks quite trivial question but after hours of searching i could not find any answer.
A simple way to include custom javascript functions in your Angular 4 project is to include the item in your assets folder, and then use require to import it into your component typescript.
src/assets/example.js
export function test() {
console.log('test');
}
src/app/app.component.ts
(before #Component(...))
declare var require: any;
const example = require('../assets/example');
(inside export class AppComponent implements OnInit { ...)
ngOnInit() {
example.test();
}

Inserting multiple services into a service - angular2

I am trying to inject a self created service & the angular2 Http service into my custom HttpRest service.
using
#Inject(Http) public _http: Http
worked fine, but when I try to inject another self made service i get following Error:
EXCEPTION: Cannot resolve all parameters for 'HttpRest'(Http #Inject(Http), undefined #Inject(undefined)). Make sure that all the parameters are decorated with Inject or have valid type annotations and that 'HttpRest' is decorated with Injectable.
For some reason
UserIds is undefined, even though the import is succesful.
My custom service:
#Injectable()
export class UserIds{
private _signature_id:string;
private _role_id:number;
get signature_id():string{
return this._signature_id;
}
set signature_id(id:string){
this._signature_id = id;
}
get role_id():number{
return this._role_id;
}
set role_id(id:number){
this._role_id = id;
}
}
The Custom HttpRest service im injecting both Http & UserIds into:
#Injectable()
export class HttpRest{
groups;
constructor(
#Inject(Http) public _http: Http,
#Inject(UserIds) public _ids: UserIds
){}
...
}
NOTE! when I remove
,
#Inject(UserIds) public _ids: UserIds
I dont get the Error.
What am I missing ?
UPDATE
The problem is actually that UserIds is undefined in the constructor params for some unknown reason that im trying to understand, so the title of this question becomes irrelevant. It should be "Imported service is undefined in constructors params".
Please reffer to my answer on this question further down this post.
UPDATE:
Please reffer to a question that discusses this issue.
Using index.ts file to export class causes undefined in injected constructor
#Inject(...) in #Inject(Http) public _http: Http is redundant when the parameter to #Inject() is the same as the type of the parameter.
#Injectable()
export class HttpRest{
groups;
constructor(public _http: Http, public _ids: UserIds
){}
...
}
You need to provide Http and UserIds so DI is able to resolve the dependency. Http is included in HTTP_PROVIDERS
#Component({
selector: '...',
providers: [HTTP_PROVIDERS, UserIds],
template: ...
})
export class AppComponent {
}
Ensure you have everything imported correctly
import {HTTP_PROVIDERS, Http} from 'angular2/http';
Ok so I found the problem, and it has not to do with Inject.
The problem was that im using an index file to export services, as mentioned in the angular 2 style guide (https://github.com/mgechev/angular2-style-guide/blob/master/old/README.md#directory-structure), and for some reason importing this specific service from the index causes an undefined value when injected into the constructor.
When I reffernced the source directly and not trough the index file, for some reason that is unknown to, resolved the Error.
The import before the fix looked like this:
import {UserIds} from "../index";
Which worked with all other services and components.
The import using the direct source file:
import {UserIds} from "../user_ids/user_ids.service";
For some reason this solved my problem, but i want to stay consistent with the index.ts encapsulation.
If anyone has an idea why this could happen I'll be happy for updates.
You need to register your UserIds service at the root level (main.ts) or in the app.component.ts, which is the highest level in the hierarchy:
#Component({
selector: 'my-app',
template: '<h1>My First Angular 2 App</h1>',
providers: [ UserIds ]
})
export class AppComponent { }

How to include external JavaScript libraries in Angular 2?

I am trying to include an external JS library in my Angular 2 app and trying to make all the methods in that JS file as a service in Angular 2 app.
For eg: lets say my JS file contains.
var hello = {
helloworld : function(){
console.log('helloworld');
},
gmorning : function(){
console.log('good morning');
}
}
So I am trying to use this JS file and reuse all the methods in this object and add it to a service, so that my service has public methods, which in turn calls this JS methods. I am trying to reuse the code, without reimplementing all the methods in my typescript based Angular 2 app. I am dependent on an external library, which I cant modify.
Please help, thank you in advance.
With ES6, you could export your variable:
export var hello = {
(...)
};
and import it like this into another module:
import {hello} from './hello-module';
assuming that the first module is located into the hello-module.js file and in the same folder than the second one. It's not necessary to have them in the same folder (you can do something like that: import {hello} from '../folder/hello-module';). What is important is that the folder is correctly handled by SystemJS (for example with the configuration in the packages block).
When using external libs which are loaded into the browser externally (e.g. by the index.html) you just need to say your services/component that it is defined via "declare" and then just use it. For example I recently used socket.io in my angular2 component:
import { Component, Input, Observable, AfterContentInit } from angular2/angular2';
import { Http } from 'angular2/http';
//needed to use socket.io! io is globally known by the browser!
declare var io:any;
#Component({
selector: 'my-weather-cmp',
template: `...`
})
export class WeatherComp implements AfterContentInit{
//the socket.io connection
public weather:any;
//the temperature stream as Observable
public temperature:Observable<number>;
//#Input() isn't set yet
constructor(public http: Http) {
const BASE_URL = 'ws://'+location.hostname+':'+location.port;
this.weather = io(BASE_URL+'/weather');
//log any messages from the message event of socket.io
this.weather.on('message', (data:any) =>{
console.log(data);
});
}
//#Input() is set now!
ngAfterContentInit():void {
//add Observable
this.temperature = Observable.fromEvent(this.weather, this.city);
}
}

Categories

Resources