I'm using a framework similar to bootstrap in Angular that provides custom HTML elements, like , and I want to update the table with a click of the button. In my typescript file, I have code to get the element
(<HTMLTableElement>document.getElementById("resultTable")).updateRows()
and the issue I'm getting is that when I cast it to a HTMLElement, the methods that are predefined such as updateRows() don't work, and I get the error message that Property updateRows doesn't exist on HTML Element. Is there a way for me to call the custom methods so I can use the custom elements? Thanks so much!
(<HTMLTableElement>document.getElementById("resultTable")).updateRows()
Why not view child?
First add a reference to the html element in the component.html file
<result-table #resultTable>...</result-table>
Then you can get that element using viewChild
export class ExampleComponent {
#ViewChild('resultTable') resultTable: ElementRef<any>;
ngAfterViewInit() {
const element = this.resultTable && this.resultTable.nativeElement ? this.resultTable.nativeElement: this.resultTable;
element.updateRows();
}
Related
I create a dynamic tootltip on target element in the following way :
var dynamicTooltip = new bootstrap.Tooltip($(targetElement));
Everything work just fine, but i would like to add to the generated tooltip a custom class.
Is not clear to me how can i target to the html generated by bootstrap with the previous instruction (or better which bootstrap API should i use to attach a class).
I see that bootstrap tooltip have a class named "tooltip" but i can't use that class to find my newly generated element eg :
$(".tooltip")
In fact i am afraid that the code above will find also already existing tooltip, and i want target only the newly generated one.
How can i achieve that?
From bootstrap docs:
Here
You can use the template option to give complex HTML structure, or just the customClass option to add custom classes:
var dynamicTooltip = new bootstrap.Tooltip($(targetElement), {
customClass: 'myCustomClass'
});
For my current project I need to pass html (and styles) to puppeteer to generate a pdf from it.
I am accessing the html by using $ref.export.$el.innerHTML but how can I access the style? My workaround until now was to create a div that contains the same style attributes so I can access it as a ref aswell.
It is important to keep the original css syntax to be able to build html out of it afterwars. I also need to get the whole style for the component, not just for single elements.
First you need to access the ref and then you just need to access styles directly or get computed styles.
template
<!-- vm.$refs.p will be the DOM node -->
<p ref="p">hello</p>
Now you could access styles via this.$refs.p.style. If you want computed styles you would need helper function as in the example below.
script
methods: {
getStylesFromRef() {
// return this.$refs.p.style if you have style attributes
// following line for computed styles
return window.getComputedStyle(this.$refs.p)
}
}
I solved the issue by using <component> in my template with is="style", that way it is not removed during compile https://stackoverflow.com/a/57331310/8773697
If I insert the html code directly in the HTML obviously that the css is noted and the element is correctly displayed.
However, if I try to dinamically create the element in javascript and insert it the css classes won't be recognized.
For example, I've tried:
var el = document.createElement("div").setAttribute("class","some_class");
(...).appendChild(el).
And el does not obey to the css rules set by some_class
The only way I've been able to do this is directly change the element properties in javascript:
var el = document.createElement("div").style.width = "20px"; //this works
(...).appendChild(el).
The element is correctly styled.
Unfortunately I wanted to go by the class names / ids.
So, any idea on how to do this? How exactly can I bind the newly created elements in javascript via _ngcontent-vkl-6 tags created after angular2 compiling?
Use Renderer or Renderer2 (if using angular 4+):
constructor(private renderer: Renderer) {}
createElement() {
const element = this.renderer.createElement(theElementToAppendTo, 'div');
this.renderer.setElementAttribute(element, 'class', 'some_class');
}
The way you're doing it isn't safe for angular, DOM manipulation should only be done via the Renderer or other bindings such as HostBinding.
This example uses the Renderer:
https://angular.io/docs/js/latest/api/core/index/Renderer-class.html
But if you're using angular 4+ you should use Renderer2 which has a different api:
https://angular.io/docs/ts/latest/api/core/index/Renderer2-class.html
I hope this helps.
I have an Angular 2 (Ionic 2) application where I hide some elements using an *ngIf if the network is offline, and show another button, "retry".
When I click the retry button, if the network is back I then want to reshow the elements hidden by the *ngIf. Also I then need to reference some of them via #ViewChild (e.g. an Ionic 2 slider to get it's current index). My problem is that these elements are not all defined when I try to get a reference to them in the same function call that sets my property bound to the *ngIf back to true.
I have tried calling from within a setTimeout but this does not seem to be very safe - some DOM elements are back but not all.
Is there a way to know then the DOM is ready with all the elements that were hidden by the *ngIf, or do I need to find some other way of doing this (not using the *ngIf, so elements are not actually removed).
Thanks in advance for any suggestions!
You should be able to do what you want by looking at the onStable event emitted via the NgZone:
In the component template:
<button (click)="showFoo = !showFoo">toggle</button>
<div *ngIf="showFoo" #foo >foo</div>
In your component class
#ViewChild('foo') foo: ElementRef;
showFoo = false;
constructor(private zone: NgZone) {
zone.onStable.subscribe(() => {
console.log(this.foo);
// this will log either undefined or an ElementRef as you toggle
});
}
Here's a plunk showing it working: https://plnkr.co/edit/jKSaEI0XUcJQehZnJTxB
I think you are looking to understand this,
I think the ngAfterViewInit() would help you with this,
ngAfterViewInit() Respond after Angular initializes the component's
views and child views.
Called once after the first ngAfterContentChecked().
A component-only hook.
I have a component (App) that contains another component (Comp). App gets string content from a database and forwards it by #Input() to Comp. This string content can contain html tags like
Some text before <a>Click</a> Some Text after
In Comp this content is supposed to be rendered and some event listeners are supposed to be added. Therefor this content is added using [innerHtml]. Because (click) is removed in [innerHtml] a reference to the a tag is needed and a event listener is supposed to be added with addEventListener. But I can't find a way to reference the a tag since an ElementRef to a component doesn't contain nativeElement.
What is the best way to get this plunker running?
https://plnkr.co/edit/xVUu0LJ02YVnBO25Zr4j?p=preview
Direct DOM access is discouraged in Angular2
Here's a hacky way to do it with direct dom access.
Define an event listener in the child comp and filter the event:
document.querySelector('body').addEventListener('click', function(event) {
if (event.target.tagName.toLowerCase() === 'a') {
that.updateCounter.next(true);
}
});
then use an EventEmitter to update the counter.
Plunker: https://plnkr.co/edit/vm44niH781j4mEQHDpLU?p=preview
In Angular2, you want to make your nested components to communicate only to their direct parent / children.
you can create a click handler for your "a" tag in your component "Comp".
In your component Comp, you can create a #Output() variable (basically an EventEmitter), that you will fire in your click handler
In the main app component, you can listen to your new EventEmitter and handle the event.
For example :
in Comp :
#Output myClickEventEmitter: EventEmitter
aTagClickHandler (e) {
myClickEventEmitter.emit(e)
}
in App template
in App Component :
myCompClickHandler(e) {
console.log(e);
}
I hope my syntax is correct here, and that it helped .
EDIT :
You should also be able to reference an inner component using the #variableName attribute in your a tag like that :
in template :
<a #variableName > </a>
in component :
#ViewChild('variableName') myATag;