How to access DOM element in other component in Angular 6? - angularjs

I have two components header & a. In header component there is a hidden element and I want to show it from component a, but I don't know how do I do this.
header.component.html
<p>
header works!
</p>
<div #hidden_element style="display: none">
<h1>Hidden Element in header</h1>
</div>
a.component.html
<div (click)="show()">Show</div>
a.component.ts
import { Component, OnInit } from '#angular/core';
#Component({
selector: 'app-a',
templateUrl: './a.component.html',
styleUrls: ['./a.component.css']
})
export class AComponent implements OnInit {
constructor() { }
show() {
// code to display hidden element in header component
}
ngOnInit() {
}
}
app.component.html
<app-header></app-header>
<app-a></app-a>

You can do it by sending events between directives via a custom service. A simple example would look something like this:
// my-service.component.ts
import { Injectable } from "#angular/core";
import { Subject } from "rxjs/index";
#Injectable()
export default class MyService {
private messageSource = new Subject<string>();
listener = this.messageSource.asObservable();
send(message: string): void {
this.messageSource.next(message);
}
}
Your 'a' component will look something like this:
// a.component.ts
import { Component, OnInit } from '#angular/core';
#Component({
selector: 'app-a',
templateUrl: './a.component.html',
styleUrls: ['./a.component.css']
})
export class AComponent implements OnInit {
constructor(private myService: MyService) { }
show() {
// code to display hidden element in header component
this.myService.send('some message');
}
ngOnInit() {
}
}
and this is your header component:
// header.component.ts
#Component({
selector: 'app-header',
templateUrl: './header.component.html',
styleUrls: []
})
export class HeaderComponent implements OnDestroy {
private serviceSubscription: Subscription;
constructor(private myService: MyService) {
this.serviceSubscription = this.myService.listener.subscribe(message => {
// TODO: Do whatever you want to do here to show the hidden element
});
}
ngOnDestroy(): void {
this.serviceSubscription.unsubscribe();
}
}

Related

Angular/Typescript - Add timestamp in array services

I'm trying to add a timestamp OnInnit in order to record the time a user accessed a page. I would like to add the timestamp in an array found in my services, but I'm really struggling to find my way around this, and keep getting errors. Any help would really be appreciated.
tracker-data.ts
export class TrackerData {
entry?: number;
exit?: number;
clicks?: number;
url?: string;
}
tracker.service.ts
import { Injectable } from '#angular/core';
import { TrackerData } from '../modules/tracker-data';
#Injectable({
providedIn: 'root'
})
export class TrackerService {
trackerData: TrackerData;
websiteData: TrackerData[];
public entryTime: {entry: number} [] = [];
constructor() { }
}
tracker.component.ts
import { Component, OnInit, OnDestroy } from '#angular/core';
import { TrackerService } from '../services/tracker.service';
import { TrackerData } from '../modules/tracker-data';
#Component({
selector: 'app-tracker',
templateUrl: './tracker.component.html',
styleUrls: ['./tracker.component.scss']
})
export class TrackerComponent implements OnInit, OnDestroy {
constructor(
public trackerService: TrackerService,
private websiteData: TrackerData[]
) { }
ngOnInit(): void {
const timeOfEntry = Date.now();
this.websiteData.push(timeOfEntry); // Type 'number' has no properties in common with type 'TrackerData'.
}
I know the above code might not make sense, but I'm fairly new to this and I'm really trying.
The error is pretty clear, you are trying to add a date (the timestamp) as an instance of TrackerData, which is clearly not. In this case you need to create an instance of the TrackerData and then assign the timestamp value.
const trackerData = new TrackerData(); // create the instance
trackerData.entry = Date.now(); // assign the the entry timestamp
this.websiteData.push(trackerData); // add to array
export class TrackerData {
entry?: number;
exit?: number;
clicks?: number = 0;
url?: string;
}
import { Injectable } from '#angular/core';
import { TrackerData } from '../modules/tracker-data';
#Injectable({
providedIn: 'root'
})
export class TrackerService {
websiteData: TrackerData[];
constructor() { }
addTrackerData(trackerData: TrackerData): void {
this.websiteData.push(trackerData);
//log data on the server if you want
}
}
import { Component, OnInit, OnDestroy } from '#angular/core';
import { TrackerService } from '../services/tracker.service';
import { TrackerData } from '../modules/tracker-data';
import { Router } from '#angular/router';
#Component({
selector: 'app-tracker',
templateUrl: './tracker.component.html',
styleUrls: ['./tracker.component.scss']
})
export class TrackerComponent implements OnInit, OnDestroy {
private pageData: TrackerData = new TrackerData();
constructor(
private trackerService: TrackerService,
private router: Router
) { }
#HostListener('click', ['$event.target'])
onClick(btn) {
this.pageData.clicks++;
}
ngOnInit(): void {
this.pageData.entry = Date.now();
this.pageData.url= this.router.url;
}
ngOnDestroy(): void {
this.pageData.exit = Date.now();
this.trackerService.addTrackerData(this.pageData);
}
this is the simplest version of what you want!
if you want to keep data when the page gets refresh, you need to put data in the cache!

Call angular method in series -Highcharts

All I'm a newbie in learning Angular and highchairs. My issue is how to call angular method in series to render charts dynamically.
I referred this link ,but i'm not understanding anything from that:
link:https://www.highcharts.com/blog/tutorials/194-using-highcharts-with-angular-js/.
link: Call an angular component method when we click on highchart series
Kindly app me to solve this.
app.component.ts
import { Component } from '#angular/core';
import { HttpClient } from '#angular/common/http';
#Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
name:string = '';
age:number;
found:boolean;
constructor(private httpClient: HttpClient) { }
onNameKeyUp(event:any){
this.name = event.target.value;
this.found = false;
}
getProfile(){
this.httpClient.get(`https://my-json-server.typicode.com/techsithgit/json-faker-directory/profiles/?name=${this.name}`)
.subscribe(
(data:any[] )=>{
if(data.length){
this.age = data[0].age;
this.found = true;
}
}
)
}
}
app.component.html
<input type ="text" (keyup) = "onNameKeyUp($event)">
<button (click)= "getProfile()">Get User Details</button>
<br>
<div *ngIf="found" >
<span>{{name}}'s age is {{age}}</span>
</div>

Passing an array between pages in ionic 2

I'm new in Ionic 2 and I'm having troubles with passing data between pages. In my Home.ts file I have a global array that contains some numbers I calculated and i want to pass it to my Table.ts file, to show it in a HTML table with the *ngFor method.
this is the Function in Home.ts where i fill the array and try to push (i will skip the calculations, becacause i know they are correct).
`import { Component } from '#angular/core';
import { AlertController } from 'ionic-angular';
import { IonicPage,NavController, NavParams} from 'ionic-angular';
import {Table} from '../table/table';
export class HomePage {
averagesList: Array <number> =[];
constructor(public alerCtrl: AlertController,
public navCtrl: NavController,
public navParams: NavParams)
{}
Calculate(){
var Averages=[];
//Calculations on the 'Averages' Array
this.averagesList = Averages;
this.navCtrl.push(Table,this.averagesList);
}
}
So I try to print it in my Table.ts file but it gives me undefined result
import { Component } from '#angular/core';
import { IonicPage, NavController, NavParams } from 'ionic-angular';
import {HomePage} from '../home/home';
#IonicPage()
#Component({
selector: 'page-table',
templateUrl: 'table.html',
})
export class Table{
constructor(public navCtrl: NavController, public navParams: NavParams) {
}
ionViewDidLoad() {
console.log(this.navParams.get('averagesList'));
}
}
I've tried to pass a let variable and it worked, so why doesn't it work with arrays?
Your mistake is using console.log(this.navParams.get('averagesList'));
Here 'averagesList' is the key.
To get it this way, you need to send as :
this.navCtrl.push(Table,{'averagesList' : this.averagesList});
Else:
if you directly send as
this.navCtrl.push(Table,this.averagesList);
You can retrieve value like so:
console.log(this.navParams.data);
you can use services to do so. Just like in angular2 you can import your service within the constructor and use the property like this.
import {OnInit} from '#angular/core';
import {someService} from ./somepath;
...
export class someClass implements OnInit{
let myTmpVar; //we will capture the shared data in this variable
constructor (private smService: someService){ ... }
ngOnInit{
this.myTmpVar = this.smService.SharedServiceData;
}
...
}
It's better to use service for passing nested data. In your case calculations object.
You can create messageService and listen to changes, something like below.
import {Injectable} from '#angular/core';
import {Observable} from 'rxjs';
import {Subject} from 'rxjs/Subject';
#Injectable()
export class LocalMsgService {
private subject = new Subject();
sendMessage(message) {
this.subject.next(message);
}
clearMessage() {
this.subject.next();
}
getMessage(): Observable<any> {
return this.subject.asObservable();
}
}
Which can be used in your home.ts and table.ts pages as follows
Home.ts
//other imports comes here
import {LocalMsgService} from 'services/localMsg';
#Component({
selector: 'home-component',
templateUrl: 'home.html'
})
export class HomePage {
constructor( private msgService: LocalMsgService) {
}
dataToPass() {
console.log(this.averagesList);
this.msgService.sendMessage(this.averagesList);
}
}
Table.ts
//other imports comes here
import {LocalMsgService} from 'services/localMsg';
import {Subscription} from 'rxjs/Subscription';
#Component({
selector: 'page-table',
templateUrl: 'table.html',
})
export class TablePage{
items: any;
subscription: Subscription;
constructor(
public localMsgService : LocalMsgService) {
this.subscription = this.localMsgService.getMessage().subscribe(msg => {
this.items = msg;
});
}
}

Angular 2 Communicating with <router-outlet> components

I have a search bar in a header component.
Beneath that, I have a "router-outlet" in that same component.
The search bar (input txtfield), once enter is pressed, needs to send the search string (event.target.value) to the component that resides within the router-outlet beneath it so that it can run a method to return the results.
I have no clue what the best way is to achieve this.
UPDATED with code..
app.component.html:
<div class="white-container">
<input name="searchStr" [(ngModel)]="searchStr" (keyup.enter)="searchCourse($event)">
</div>
<router-outlet></router-outlet>
app.component.ts:
import { Component, OnInit } from '#angular/core';
import { CourseService } from './services/courses.service';
import { Course } from './Course';
#Component({
selector: 'my-app',
templateUrl: 'app.component.html',
providers: [CourseService]
})
export class AppComponent implements OnInit {
constructor(private _courseService: CourseService) {
}
searchCourse(event) {
// the user search string here...
}
}
/course-listings/course-listings.component.ts:
import { Component, OnInit } from '#angular/core';
import { CourseService } from './services/courses.service';
import { Course } from './Course';
#Component({
selector: 'app-course-listings',
templateUrl: './course-listings.component.html',
styleUrls: ['./course-listings.component.css'],
providers: [CourseService]
})
export class AppComponent implements OnInit {
course: Course[];
constructor(private _courseService: CourseService) {
}
searchCourse(evt) {
// This works once it's fired...
this._courseService.findCourse(evt)
.subscribe(courses => {
this.course = courses;
});
}
}
/services/courses.service.ts:
import {Injectable} from '#angular/core';
import {Http} from '#angular/http';
import 'rxjs/add/operator/map';
#Injectable()
export class CourseService {
constructor(private _http:Http) {
}
getCourses(search) {
return this._http.get('/api/v1/courses/'+search)
.map(res => res.json());
}
}
FIX FOUND
Günter Zöchbauer was correct. I used a service w/ subscribe and observables to do it. Thanks.
An event.subscriber would be required in the constructor to pass to router-outlet.
Similar to the answer in this Angular 2 router event listener.
So, once the click is done, the subscriber event will be executed based on on the navigationend event, then the value can be accessed.

Angular 2 I don't know how to delete a row of a pushed Object

First let me be clear about my problem/issue:
First it was like this: https://www.dropbox.com/s/92z2oe7f4w5x2b5/conditions.jpg?dl=0 Here it deletes the last created Object in my case Conditions.
but i want to delete each condition separately like this see the red box next to each row: https://www.dropbox.com/s/ptwq6sk6da4p21k/new.jpg?dl=0
import {Component, OnInit, DynamicComponentLoader, Input} from 'angular2/core';
import {Condition} from './condition';
import {DateCondition} from './datecondition.component';
import {StringCondition} from './stringcondition.component';
import {SelectCondition} from './selectcondition.component';
import {ConditionDetailComponent} from './conditiondetail.component';
import {ConditionService} from './condition.service'
#Component({
selector: 'condition-builder',
templateUrl: 'app/conditionbuilder.component.html',
directives: [ConditionDetailComponent],
})
export class ConditionBuilderComponent implements OnInit {
conditions: Condition[] = [];
catalog: Condition[] = [];
constructor(public _conditionService: ConditionService) { }
getConditions() {
this._conditionService.getConditions().then(conditions => this.catalog = conditions);
}
ngOnInit() {
this.getConditions();
}
onChange(conditionsIndex, selectedCondition:string): void {
this.conditions[conditionsIndex] = this.catalog.find(condition => condition.name == selectedCondition);
}
newCondition() {
this.conditions.push(this.catalog[0]);
}
deleteCondition() {
this.conditions.pop();
}
}
In the code above i'll import the getConditions with the object of conditions in my case. Does any one know how i do this and what is the best way to handle this issue?
Here i want to
import {Component, OnInit, Input, DynamicComponentLoader, ElementRef} from 'angular2/core';
import {Condition} from './condition';
import {DateCondition} from './datecondition.component';
import {StringCondition} from './stringcondition.component';
import {SelectCondition} from './selectcondition.component';
import {ConditionBuilderComponent} from "./conditionbuilder.component";
#Component({
selector: 'condition-detail',
template: '<div #child></div>'
+ '<a class="btn btn-danger" (click)="deleteCondition()"><i class="glyphicon glyphicon-minus"></i></a>'
})
export class ConditionDetailComponent implements OnInit {
#Input() condition: Condition;
dcl:DynamicComponentLoader;
elementRef:ElementRef;
constructor(dcl: DynamicComponentLoader, elementRef: ElementRef) {
this.dcl = dcl;
this.elementRef = elementRef;
}
ngOnInit() {
this.dcl.loadIntoLocation(this.condition, this.elementRef, 'child');
}
deleteCondition() {
HOW CAN I DELETE THE CONDITION ROW HERE?
}
Like this is the code build, ill hope it is clear for you to help me out. How does the deleteCondition method know which row he needs to deleten and how do i delete it out of the array in the code above the page?
Ill hope someone can help me out!!
You could provide the list to the sub component and remove the current element from it. This way the associated component in the loop will be removed.
The main component:
#Component({
selector: 'my-app',
template: `
<div *ngFor="#elt of data">
<my-component [elt]="elt" [data]="data"></my-component>
</div>
`,
directives: [MyComponent]
})
export class AppComponent {
constructor() {
this.data = [
{name: 'name1'},
{name: 'name2'},
{name: 'name3'},
{name: 'name4'}
];
}
}
The child component:
#Component({
selector: 'my-component',
template: `
<div>{{elt.name}} <span (click)="delete()">X</span></div>
`
})
export class MyComponent {
#Input()
elt: any;
#Input()
data: any[];
delete() {
var index = this.data.indexOf(this.elt);
this.data.splice(index, 1);
}
}
See this plunkr: https://plnkr.co/edit/o5O0Rr?p=preview.

Resources