0

(click) event in typescript causes error given below.

EXCEPTION: Error during evaluation of "click"
ORIGINAL EXCEPTION: TypeError: Cannot read property 'appendChild' of undefined
angular2.dev.js:23877 ORIGINAL STACKTRACE:
angular2.dev.js:23877 TypeError: Cannot read property 'appendChild' of undefined
at Playlist.addVideo (playlist.component.ts:53)
at ChangeDetector_Playlist_0.handleEventInternal (viewFactory_Playlist:62)
at ChangeDetector_Playlist_0.AbstractChangeDetector.handleEvent (angular2.dev.js:9568)
at AppView.triggerEventHandlers (angular2.dev.js:10246)
at eval (viewFactory_Playlist:361)
at angular2.dev.js:14068
at angular2.dev.js:13496
at ZoneDelegate.invoke (angular2-polyfills.js:332)
at Object.onInvoke (angular2.dev.js:2111)
at ZoneDelegate.invoke (angular2-polyfills.js:331)
ERROR CONTEXT:
BrowserDomAdapter.logError @ angular2.dev.js:23877
ExceptionHandler.call @ angular2.dev.js:1333
(anonymous) @ angular2.dev.js:12763
schedulerFn @ angular2.dev.js:13167
SafeSubscriber.__tryOrUnsub @ Rx.js:10775
SafeSubscriber.next @ Rx.js:10730
Subscriber._next @ Rx.js:10690
Subscriber.next @ Rx.js:10667
Subject._finalNext @ Rx.js:11191
Subject._next @ Rx.js:11183
Subject.next @ Rx.js:11142
EventEmitter.emit @ angular2.dev.js:13148
onError @ angular2.dev.js:13566
onHandleError @ angular2.dev.js:2128
ZoneDelegate.handleError @ angular2-polyfills.js:336
Zone.runGuarded @ angular2-polyfills.js:244
NgZoneImpl.runInner @ angular2.dev.js:2140
NgZone.run @ angular2.dev.js:13649
outsideHandler @ angular2.dev.js:13495
ZoneDelegate.invokeTask @ angular2-polyfills.js:365
Zone.runTask @ angular2-polyfills.js:263
ZoneTask.invoke @ angular2-polyfills.js:431
angular2.dev.js:23877 EventEvaluationErrorContext {element: button.btn.btn-success, componentElement: playlist, context: Playlist, locals: Object, injector: Injector}

I want that when I click on add Video button a dynamically generated new editable row will append to table, whose value I want to pass to another class.

inputTitle: HTMLInputElement;
inputLink: HTMLInputElement;
td: HTMLTableCellElement;
tdTitle: HTMLTableCellElement;
tdLink: HTMLTableCellElement;
tr: HTMLTableRowElement;
tBody: HTMLElement = document.getElementsByTagName("tbody")[0];

addVideo()
{
    this.inputTitle = document.createElement("input");
    this.inputLink = document.createElement("input");
    this.td = document.createElement("td");
    this.tdTitle = document.createElement("td");
    this.tdLink = document.createElement("td");
    this.tr = document.createElement("tr");

    this.inputTitle.setAttribute("type", "text");
    this.div.appendChild(this.inputTitle);
    this.inputLink.setAttribute("type", "text");

    this.tdTitle.appendChild(this.inputTitle);
    this.tdLink.appendChild(this.inputLink);

    this.tr.appendChild(this.td);
    this.tr.appendChild(this.tdTitle);
    this.tr.appendChild(this.tdLink);

    this.tBody.appendChild(this.tr);
}

And also the above method works fine. But this addVideo() cause problem.

Click here to see what I want. If anyone got other suggestion kindly tell me. Thanks.

Here's playlist.component.ts file

import {Component, Input} from "angular2/core";
import {Video} from "./video";
@Component(
{
selector: "playlist",
templateUrl: "app/ts/playlist.component.html",
inputs: ["videos"]
})
export class Playlist
{
iframe: HTMLIFrameElement;
div: HTMLDivElement = document.getElementsByTagName("div")[0];  
inputTitle: HTMLInputElement;
inputLink: HTMLInputElement;
td: HTMLTableCellElement;
tdTitle: HTMLTableCellElement;
tdLink: HTMLTableCellElement;
tr: HTMLTableRowElement;
tBody: HTMLElement = document.getElementsByTagName("tbody")[0]; 
onSelect(vid: Video)
{
    if(this.iframe)
        this.div.removeChild(this.iframe);
    this.iframe = document.createElement("iframe");
    this.iframe.setAttribute("width", "800");
    this.iframe.setAttribute("height", "500");
    this.iframe.setAttribute("src", "https://www.youtube.com/embed/" + vid.link);
    this.div.appendChild(this.iframe);
}
addVideo()
{
    this.inputTitle = document.createElement("input");
    this.inputLink = document.createElement("input");
    this.td = document.createElement("td");
    this.tdTitle = document.createElement("td");
    this.tdLink = document.createElement("td");
    this.tr = document.createElement("tr");

    this.inputTitle.setAttribute("type", "text");
    this.div.appendChild(this.inputTitle);
    this.inputLink.setAttribute("type", "text");

    this.tdTitle.appendChild(this.inputTitle);
    this.tdLink.appendChild(this.inputLink);

    this.tr.appendChild(this.td);
    this.tr.appendChild(this.tdTitle);
    this.tr.appendChild(this.tdLink);

    this.tBody.appendChild(this.tr);
}

}

Here's playlist.component.html file

<div>
<div style = "position: relative;" class = "btn-group">
    <button class = "btn btn-success" (click) = "addVideo()">Add Video</button>
    <button class = "btn">Edit <span class = "glyphicon glyphicon-pencil"></span></button>
</div>
<div class = "table-responsive">
    <table class = "table table-striped table-hover" border = "0">
        <thead>
            <tr style ="font-weight: bold">
                <td>ID</td>
                <td>Title</td>
                <td>Video Code</td>
            </tr>
        </thead>
        <tbody id = "VideoEntries">
            <tr *ngFor = "#v of videos" (click) = "onSelect(v)">
                <td>{{v.id}}</td>
                <td>{{v.title}}</td>
                <td>{{v.link}}</td>
            </tr>
        </tbody>
    </table>
</div>

Here's app.component.ts file

import {Component} from "angular2/core";
import {Video} from "./video";
import {Config} from "./config.service";
import {Playlist} from "./playlist.component";
@Component(
{
selector: "my-app",
templateUrl: "app/ts/app.component.html",
directives: [Playlist]
})

export class AppComponent
{
Heading = Config.HEADING;
videos: Array<Video>;
constructor()
{
    this.videos =
    [
        new Video(1, "Angular1", "hXfigUyeHaY"),
        new Video(2, "Angular2", "MyqcsnbH820")
    ]
}

}

1 Answer 1

1

you are trying to use undefined variable.

you have declared those parameters:

inputTitle: HTMLInputElement;
inputLink: HTMLInputElement;
td: HTMLTableCellElement;
tdTitle: HTMLTableCellElement;
tdLink: HTMLTableCellElement;
tr: HTMLTableRowElement;
tBody: HTMLElement = document.getElementsByTagName("tbody")[0];

you need also to declare your 'div'.

this.div.appendChild(this.inputTitle);

but note you do not have any 'div' defined.

Sign up to request clarification or add additional context in comments.

6 Comments

and why this is undefined? @yalin
Sorry I forgot to remove tBody: HTMLElement = document.getElementsByTagName("tbody")[0]; I'm accessing div element from template file div: HTMLDivElement = document.getElementsByTagName("div")[0]; here I've declared this. @Yalin
I was saying that, I forgot to remove tBody in this post. But in actual code I'm using div. But still not working. @Yalin
can you tell me what line is: playlist.component.ts:53 ? this is the problematic line.
Yeah I got it. Thanks
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.