Pass JSON data from App Component to another component in Angular 6 - json

I have two components,
1. App Component
2. Main Component
app.component.ts
ngOnInit () {
this.httpService.get('./assets/batch_json_data.json').subscribe(data => {
this.batchJson = data as string [];
}
I am able to get the JSON from a file into 'batchJson' and need to pass this to my main component for further operations.
There is no event or anything that triggers this.
I have not implemented anything yet, I am trying to read #Input, #Output etc but do not understand how it works and need to go through it some more.
I have just declared basics in the main.component.ts
import { Component, OnInit, ViewChild, Input } from '#angular/core';
import { AppComponent } from '../app.component';
export class MainComponent implements OnInit {
}
Please help me out, I am an absolute rookie in Angular and am unable to try anything because my concepts are not clear and I did browse Stack Overflow, the answers are not matching my requirements.

One solution could be to use a public BehaviorSubject in your app.component.ts.
public batchJson$ = new BehaviorSubject<JSON>(null);
ngOnInit () {
this.httpService.get('./assets/batch_json_data.json').subscribe(data => {
this.batchJson = data as string [];
this.batchJson$.next(JSON.parse(data));
}
Then in your main.component.ts
constructor(private _appComponent : AppComponent )
ngOnInit(){
this._appComponent.batchJson$.subscribe((data)=>{
if(data != null){
//set data to local variable here
}
})
}
Typically I store this kind of logic in a Service, using this in a component will definitely get you pointed in the right direction to learning this concept. Preferably your component should be responsible for interacting with the UI and rendering data, while your services handle retrieving and distributing data.

you can implement common service which does all related http operations and you can inject this service in any component u want and read the json.
Make sure you return the http.get and you subscribe to it where ever you call this method.
If you are not aware of services , you can read about creating and injecting services in angular

You can use rxjs subject to emit the data through out the app and fetch it anywhere by using subject.getValue() method.

First of all you should spare time on understanding the concept of any technology before you start working on it. Else you would be spending most of the time seeking help.
I had created demo here - https://stackblitz.com/edit/angular-lko7pa. I hope it will help you out.

Related

Is there a way to print value in variable in angular4 component from console?

I save simple key in a variable in a component using angular 4, when the app closed every value will erased and i know it.
this is a simple sample :
export class LoginComponent implements OnInit {
data : any;
constructor() {
this.data = "Hello";
}
}
I just want to know is there a way using browser console to show value in this.data without console.log()?
Yes you can.
Start by finding some HTML that belongs to your component in your page. Then, inspect it.
In Chrome, you will see a $0 besides it. That's a variable reference.
Now, go into your console and type
ng.probe($0).componentInstance
This will log you your whole component, with the variables that are in it. You can simply give it a reference
const myRef = ng.probe($0).componentInstance
Then delete your component as you want, and log it again from the console directly
console.log(myRef) // or shorthand
myRef

what would be the data type in this json like data?

I am creating an HTTP request to the back end thru this angular implementation.
I prepared the app.module by first importing the {HttpClientModule} from '#angular/common/http' into the app.module and then adding it to the imports array making it available to the rest of the app.
then, I use the get method on HttpClient to access the data in my server
That's the game plan.
The question is about determining the data type to be returned by the server.
The component has this code... I cut the not-needed stuff for brevity.
#Component(...)
export class MyComponent implements OnInit {
// results: string[]; // I am not sure about this
constructor(private http: HttpClient) {}
ngOnInit(): void {
url = 'http://example.com/authentication/get-username.php';
http
.get<MyJsonData>(url)
.subscribe...
}
My question is..
What should I type-cast where it says ? in the above code?
Little bit more backgrond:
the URL returns something like this:
{"wordpress_username":"admin_joe","user_role":"admin"}
or if no user logged in, this
{"wordpress_username":"","user_role":""}
now, here, we got a a format like {"x":"y", "j":"k"}
this is a json string. but, it is also an object
And this is where my confusion starts.
Would it be better to build an interface for this?
If so, what would be the interface look like?
Using Typescript is preferred for its strong typing also on the level of the Typescript. It is better to have a type for that.
In both cases you have the same shape of your object with two properties wordpress_username and user_role. Your interface can look like this
export interface MyJsonData {
wordpress_username: string,
user_role: string
}
Also if you can have a response with only one property, you can make them optional appending ? at the end of the property name
export interface MyJsonData {
wordpress_username?: string,
user_role?: string
}

Angular 2 functions library

In my application I'll need to create a functions library to be accessed from different components. What is the best way to do this? Do I need to make a service with all the functions or a class or a module or a component?
In this library if I call a function from a component and this function need to access a variable in the caller, will it be possible to do?
If it's just a set of one off helper functions the easiest way is create an #Injectable service with your helper methods then inject that into any component that requires them. You can provide public vars as well so they're accessible in your html.
#Injectable()
export class Helpers {
helper1() { return "hello"; }
helper2(x) { return x + 1 }
}
#Component({
providers: [Helpers],
template: "<div>{{helper1()}}</div>" // will display 'hello'
)}
export class MyComponent {
public helper1: Function = Helpers.helper1;
constructor() {
console.log(Helpers.helper2(5)); // will output '6'
}
}
This works great for a simple set of random utility functions. If you need something more in depth please explain and we can provide alternate solutions.

angular 2 RC4 create component

So here is the problem, I am attempting to create a new component from within a service that is injected within the App Component. I need the new component to be placed within the app component html tag not outside. The thing is I really do not want the app component to have to provide anything to the service I may need to inject the service into other places and hence not have it tightly coupled to the app component. So far I have created a DIV at the end of the app component html and then used #ViewChild to read the ViewContainerRef from this element located within the app component. This is then provided to the service via a function call so that it can make use of createComponent. This allows for the NEW component to be placed within the scope of the app component, not within the body. Unfortunately this is too dependant on the app component providing the ViewContainerRef. Any ideas of how I can create the new component as described.
Code Example
app.component.html
<app-component>
<div #newCompHook></div>
</app-component>
app.component.ts
#ViewChild('newCompHook', {read: ViewContainerRef}) newCompViewRef: ViewContainerRef;
constructor(appService: AppService) {
appService.setViewRef(this.newCompViewRef);
}
app.service.ts
private myViewRef;
constructor(private compiler: ComponentResolver){
this.myViewRef = null;
}
public setViewRef(vr: ViewContainerRef): void {
this.myViewRef = vr; // <-- DO NOT WANT TO DO THIS !!!
}
public createNewComp(childCmp: Type): void {
if (this.myViewRef !== null){
this.compiler.resolveComponent( childCmp ).then((compFactory:ComponentFactory) => this.myViewRef.createComponent(compFactory) )
}
}
createNewComp is called by an external source and may or may not provide the childCmp type to be resolved.
So any ideas of how I can do this without needing to provide anything from the app component ???
If you need to have the viewContainerRef in your service that is the only solution...
But it is not a good practice to generate HCI components in a service. It's the role of other components.
Let's take an exemple : your server send you a list of objects (a list of strings for exemple) and you want to generate a button for each string.
In your service you just manage the string list :
#Injectable()
export class MyService {
private myModel : Array<String> = new Array();
public get MyModel () : Array<String> {
return this.myModel;
}
/// Assume you have method in the service to populate the model...
}
Then it's your component which generate the HCI :
export class AppComponent {
/// Use dependency injection to get service :
constructor (private _myService : MyService){}
public get MyModel () : Array<String> {
return this.myService.MyModel;
}
}
Finally in your component template :
<div>
<ul>
<li *ngFor="let s of MyModel">
<!-- Button with your model text -->
<button>s</button>
</li>
</ul>
</div>
That is a better solution than generate the components in the service because just imagine you don't want buttons list but a togglebuttons list in your HCI, here you just have to change the HTML. The service is still the same, and the components typescipt part is still the same too !

Where to load the server data

I'm using the react-router and navigate to a component that gets an ID in the URL and has to use this ID to get data from the server with the help of an action.
At the moment I'm calling the action creator in the componentWillMount hook.
This works so far, but brings a problem.
In the render method I have to check, if myData really exists with all its attributes, before I can really render.
#connect(state => {myData: state.etc.myData})
export default class extends React.Component {
componentWillMount = () => {
this.props.dispatch(
ActionCreators.getData(this.props.params.id)
)
}
render() {
if (this.props.myData.hasNotLoaded) return <br/>
...
}
}
Is there another way to get data into the store before rendering without manual checks?
You can subscribe to router's onEnter hook and dispatch actions from where.
const store = configureStore()
const routing = (<Router>
<IndexRoute onEnter={()=>store.dispatch(myLoadDataActionCreator())}/>
</Router>)
So you can avoid setState from previous answer and don't tie up component with redux.
You should create a call back, for example:
_onChange() {
this.setState(myStore.getData());
}
Then in the following react functions do the following:
componentDidMount() {
myStore.addChangeListener(this._onChange);
},
componentWillUnmount() {
myStore.removeChangeListener(this._onChange);
}
I assume you're using the mixins for the react-router, if not, take a look at the docs for it, they have some useful functions that are worth looking at.
I don't think you will need that if logic in the render() method, react will handle that with the virtual dom management and know when to load it and the data.