I am working on the front end of a file upload service. I am currently ignoring the service path with respect to the backend. I have run into a strange problem. I have a few generated components that sit within the app component. When I end the serve from console and do ng serve again, it errors out. It says:
The only way I have found to get rid of this is to erase my uploader service injection, save the file, then re-insert the injection. This is how it is supposed to look:
The only way to get ng serve to work is to by erasing the line private service: UploaderService
Any idea why this is happening? Am I missing something with my injection? My UploaderService is marked as Injectable() and the components that use it are under Directives.
Update:
What I found out is that it is unrelated to the UploaderService. I have a component that does not inject the UploaderService. I fix it the same way I fix the other components that inject the UploaderService. By deleting the parameters of the constructor, saving, and then putting the parameters back. Then it will serve
Update2:
The generated componenet, upload.component.t, has a spec file that is generated with it, upload.component.spec.ts
It has a error that asks for parameters like so:
My UploadComponent constructor has a parameter in it, where i inject the UploaderService. In the spec.ts file, a new UploadCompent is created, but does not contain any arguments. I am guessing this is where I am going wrong. How do I work around this?
Here is my UploaderService:
import { Injectable } from '#angular/core';
import {Http, Response, HTTP_PROVIDERS, Headers, HTTP_BINDINGS, RequestOptions} from '#angular/http';
import { Observable } from 'rxjs/Observable';
import 'rxjs/Rx';
import { ItemEntryComponent } from './item-entry';
import { Query } from './Query';
#Injectable()
export class UploaderService {
public URL: string;
private query: Query;
public filesSelected: Array<ItemEntryComponent> = [];
progress$: any;
progress: any;
progressObserver: any;
//CONSTRUCTOR
constructor(private http: Http) {
//***SET URL***
this.URL = 'http://localhost:7547/api/picker';
//Create Query for url
this.query = new Query(this.URL);
//Create progress attribute
this.progress$ = Observable.create(observer => {
this.progressObserver = observer
}).share();
}
}
Problem solved!
I had not realized the generated files included a spec testing file, in my example it was upload.component.spec.ts. Getting rid of those files gets rid of the errors that ask for parameters to be filled in inside the test files and now ng serve works.
Related
I want to update my JSON file which I have placed in my assets folder, so If I am updating just one property of my JSON object so it should update that property only, without affecting any other properties value:
Let the sample code be :
loginInterface.ts
export interface loginModel {
Email: string;
Password: string;
}
login.component.ts
import { Component, OnInit } from '#angular/core';
import { Observable } from 'rxjs';
import { HttpClient } from '#angular/common/http'
import { loginModel } from './loginModel'
#Component({
selector: 'app-login',
templateUrl: './login.component.html',
styleUrls: ['./login.component.css']
})
export class LoginComponent implements OnInit {
private _jsonURL = 'assets/Login.json';
private login: Array<loginModel>;
constructor(
private http: HttpClient) {
this.login = new Array<loginModel>();
}
ngOnInit() {
this.getLoginData();
}
getLoginData() {
this.http.get<loginModel[]>(this._jsonURL).subscribe(data => {
this.login = data;
console.log(this.login);
return this.login;
});
}
UpdateLoginData() {
// How to proceed on this one??
}
}
login.component.html
<div *ngFor = "let log of login">
{{log.Email}}
<input [ngModel]="log.Password">
</div>
<button (click)="UpdateLoginData()">Update</button>
This is just an example.
So if I am changing password at one place and clicking on update button , then it should update password of that specific Email only and I don't want to replace the whole file with new JSON object just for updating a single value, is this possible?
You can't do any file operation using just angular framework. You need server side implementation to achieve this. If you are not familiar with server side programming you can try using in memory angular database api.
https://www.npmjs.com/package/angular-in-memory-web-api
You can't change the content of JSON file directly through angular, you need the Backend in order to reflect the change on that JSON file.
No! You cannot change a file’s content using Angular. It is a file I/O operation that is handled by a backend framework/language (for example Node.JS) having file system API. You can create a RESTful API to modify the contents of the file and make an HTTP call from Angular.
In json server you can update using put method
//somewhat like given below
this.http.put(this._jsonURL+this.login[0].id,this.login[0]).subscribe();
I am writing application in Angular 8 (8.0.3) and I need to import external JS file which will hold a URL reference for API that can and will change. The problem I am facing is that changes I do into this file after I have compiled Angular app (with ng build --prod), changes are not being picked up inside Angular, but it keeps the data as it was when the app was built.
This is the external JS file:
export function apiUrl() {
return 'http://www.localhost.local/api/v1/';
}
The apiUrl() does return proper value, but if I change it, the updated value is not reflected inside Angular app.
I also created .d.ts. file:
export declare function apiUrl();
Imported the external JS file into index.html:
<script type="module" src="assets/js/api_url.js"></script>
Used it in angular service:
import {apiUrl} from '../../assets/js/api_url';
export class ApiService {
private api_url: string = apiUrl();
constructor(...) {
console.log(apiUrl());
}
}
I did NOT import this file in angular.json and even if I do, nothing changes.
So, how to create and then import an external JS file that after it changes, the Angular app does pick up it changes?
EDIT:
Do note that I do not need a live app reload when this file changes, but I need for the file to be loaded from server each time the Angular app starts.
EDIT 2:
To explain why I need this. The Angular app will be used on internal network to which I do not have access to. The client currently does not know the API URL and even if he would, it can change at any moment. That's the reason why I need this to work.
In that case you should use environments
You can find them in src/environments directory.
For local development you have environment.ts file, for production environment.prod.ts
Example environment.ts:
export const environment = {
production: false,
apiUrl: 'http://www.localhost.local/api/v1/'
};
environment.prod.ts:
export const environment = {
production: true,
apiUrl: 'http://www.producitonurl.com/api/v1/'
};
To use this apiUrl value you need to import environment file in typescript file like this:
You need to import environment.ts not any other environment file, because angular is replacing it while building application
import {environment} from '../environments/environment';
#Injectable({
providedIn: 'root'
})
export class MyApiService {
apiUrl = environment.apiUrl;
}
But in case you want to use method from <script type="module" src="assets/js/api_url.js"></script>, just use window object like this:
private api_url: string = (window as any).apiUrl();
what i want : i have a config file where it contains some urls in .json file stored in asset folder now instead of loading environments.prod or .ts i want to load my json file config and basing on that i want run my application
what i did
below is my json file which i placed asset folder
{
"baseUrl": "https://jsonplaceholder.typicode.com/",
"baseUrl2": "https://reqres.in/api/users"
}
now i created a ConfigServiceService.ts fpr storing config file
public _config: Object;
constructor(public http:Http) { }
getData(){
debugger;
return this.http.get("./assets/config.json").pipe(map(res => res.json()));
}
after this i create a ServiceProviderService.ts for calling the service file
configData:any;
constructor(public http:Http,public config:ConfigServiceService) {
}
jsonData(){
debugger;
return this.configData;
}
ngOnInit(){
debugger;
this.config.getData().subscribe(res =>{
console.log(res);
this.configData = res;
});
}
now i am calling the app.component.ts
title = 'sample';
constructor(public serv :ServiceProviderService){
this.serv.jsonData();
}
now my issue is i am not able to get the json data and if i am putting the logic which is there is ngoninit in ServiceProviderService.ts file if put it in constructor then i am getting undefined
note : here if there are more that once url then each url is distributed to various seperate service file suppose base1 url for 1 service file ans base2 url for another file how can i achieve that
To access the assets folder. Make sure angular.json has a reference under
architect --> build -->options to the directory where the file is stored:
"assets": [
"src/favicon.ico",
"src/assets"
],
Try giving it an absolute url and it should work
Here, give this a try:
import { Injectable } from '#angular/core';
import { HttpClient } from '#angular/common/http';
#Injectable()
export class ConfigService {
constructor(private http: HttpClient) { }
getData() {
return this.http.get('/assets/config.json');
}
}
Here's a Working Sample StackBlitz for your ref.
In Angular only components have lifecycle hooks (like ngOnInit, ngOnDestroy etc), services haven't. In services you should use their constructor instead.
I have some external application that provide config.json for my Angular 2 application.
I need point of entry for my angular 2 like:
angular2Application.setConfig('../config.json'); // in browser console e.g.
(then i can use this json in any my service of angular2 app)
and also my app should be able to send some data from service to any external app by the calling some method like:
var config = angular2Application.getConfig(); // in external other JS application
Probably i should do external calls through global window ? Any help and advices or examples will appreciated.
My angular 2 app service which has global config to be shared.
"Another js app" - this means another js application in the same window.
import {Injectable} from "#angular/core";
import {Observable} from "rxjs";
import {SomeService} from "../../some.service";
#Injectable()
export class SharingService {
public config; // the external app should be able to get this config
constructor(public someService: SomeService) {
this.someService.dataChanged.subscribe(
(data) => {
this.config = data;
}
);
}
}
You can use something like socket.io and create a socket communication between two applications.
I'm using sanitizer.bypassSecurityTrustUrl to put links to blobURL's on the page. This works just fine as long as I don't AoT compile the project.
import {DomSanitizer} from '#angular/platform-browser';
export class AppComponent {
constructor(private sanitizer: DomSanitizer) {
}
sanitize(url: string) {
return this.sanitizer.bypassSecurityTrustUrl(url);
}
}
The sanitize function takes a URL like this:
blob:http://localhost:4200/7c1d7221-aa0e-4d98-803d-b9be6400865b
If I use AoT compilation I get this error message:
Module build failed: Error: /.../src/app/app.component.ts (18,3):
Return type of public method from exported class has or is using name
'SafeUrl' from external module
"/.../node_modules/#angular/platform-browser/src/security/dom_sanitization_service"
but cannot be named.)
I'm using CLI with Angular 2.1.0
Anybody knows how I can circumvent this problem? Or should it be reported as a bug?
So it seems I had to add a return type of SafeUrl to the method
sanitize(url: string):SafeUrl {
return this.sanitizer.bypassSecurityTrustUrl(url);
}
Big thanks to alxhub
In my case i was initiating an attribute like this :
public img64 = this.domSanitizer.bypassSecurityTrustResourceUrl('data:image/jpg;base64,' + this.base64Image);
Resulting in the same error.
Thanks to #mottosson I got it right (just add the type SafeUrl):
public img64: SafeUrl = this.domSanitizer.bypassSecurityTrustResourceUrl('data:image/jpg;base64,' + this.base64Image);