I want to pass data from a grandparent to a grandchild. Using @Input seems cumbersome because I'd have to use it twice - I also believe it would make refactoring harder, if for example these components became siblings.
In other words, I want to avoid using @Input twice, one in the child, one in the grandchildren, for passing the same piece of data. I currently prefer using shared services to share data.
Here is the HTML:
// grandparent
<div *ngIf="daPanel.expanded === true">
<div *ngFor="let e of elements;">
<app-history-item-tab-group></app-history-item-tab-group>
</div>
</div>
// child
<div>
<mat-tab-group>
<mat-tab label="Settings">
<app-history-settings></app-history-settings>
</mat-tab>
<mat-tab label="Events List">
<app-history-events-list></app-history-events-list>
</mat-tab>
<mat-tab label="Generated Code">
<app-history-generated-code></app-history-generated-code>
</mat-tab>
</mat-tab-group>
</div>
// grandchild
<div class="language-js">
<mat-card>
<button id="copy-code-btn" style="float:right;"
mat-raised-button (click)="copyCodeToClipboard()">Copy Code to Clipboard</button>
<button style="float:right;" mat-raised-button>Save Code to File</button>
<mat-card-title>Here is your generated code</mat-card-title>
<mat-card-subtitle>JavaScript</mat-card-subtitle>
<mat-card-content [style.overflow]="'auto'" [style.height.px]="'500'">
<pre [innerHTML]="highlightedCode"></pre>
</mat-card-content>
<mat-card-actions>
<button mat-button>LIKE</button>
<button mat-button>SHARE</button>
</mat-card-actions>
<mat-card-footer></mat-card-footer>
</mat-card>
</div>
As opposed to using @Input to pass data, I'd rather share a unique instance of a service between the components, but I don't know how to do that.
To be exact - ideally I could create a unique service instance for the grandparent, and share a reference to that unique service in the grandparent, the child, and the grandchild...but how?
Here is the grandparent component:
@Component({
moduleId: module.id,
templateUrl: './history.component.html',
styleUrls: ['./history.component.scss'],
encapsulation: ViewEncapsulation.None,
preserveWhitespaces: false,
})
export class HistoryComponent implements OnInit {
displayMode: string = 'default';
multi = false;
hideToggle = false;
disabled = false;
showPanel3 = true;
expandedHeight: string;
collapsedHeight: string;
elements : Array<any>;
constructor(private mds: MainDataService) {
const v = this.mds.key;
this.elements = JSON.parse(localStorage.getItem(v) || '[]');
}
ngOnInit() {
}
}
Here is the child component:
@Component({
selector: 'app-history-item-tab-group',
templateUrl: './tab-group-history.component.html',
styleUrls: ['./tab-group-history.component.scss']
})
export class TabGroupHistoryComponent implements OnInit {
constructor() {
}
ngOnInit() {
}
}
Here is the grandchild component:
@Component({
selector: 'app-history-generated-code',
templateUrl: './history-generated-code.component.html',
styleUrls: ['./history-generated-code.component.scss'],
styles: [`
mat-card { margin:2em; }
`]
})
@Inject(ChromeDataService)
@Inject(MainDataService)
export class HistoryGeneratedCodeComponent implements OnInit {
highlightedCode: string;
googleCodo: string;
rawCode = '';
mySub: Subscription;
codeTreeRoot = values.top.copy();
currentNode = this.codeTreeRoot;
rawGeneratedCode = '';
formattedCode: string;
constructor(private mds: MainDataService) {
this.formattedCode = ' // (no code generated yet)';
this.highlightedCode = Prism.highlight(this.formattedCode, Prism.languages.js);
}
ngOnInit() {
}
ngOnDestroy() {
this.mySub.unsubscribe();
}
ngAfterContentInit() {
Prism.highlightAll(true, function () {
console.log('highlighted...');
});
}
copyCodeToClipboard() {
const textarea = document.createElement('textarea');
textarea.setAttribute('type', 'hidden');
textarea.textContent = this.formattedCode || this.rawCode;
document.body.appendChild(textarea);
// textarea.focus();
textarea.select();
document.execCommand('copy');
textarea.parentNode.removeChild(textarea);
}
updateCode() {
this.rawGeneratedCode = this.codeTreeRoot.generate();
this.formattedCode = js_beautify(this.rawGeneratedCode, {
brace_style: 'preserve-inline',
max_preserve_newlines: 2
});
this.highlightedCode = Prism.highlight(this.formattedCode, Prism.languages.js);
}
}