(单击)angular2中的事件抛出错误,打字稿

时间:2017-06-06 08:02:08

标签: html angular typescript click angular2-directives

(点击)打字稿中的事件导致下面给出的错误。

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}

我希望当我点击“添加视频”按钮时,动态生成的新可编辑行将附加到表,我想将其值传递给另一个类。

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);
}

此外,上述方法也可以。但是这个addVideo()会导致问题。

点击here查看我想要的内容。如果有人有其他建议,请告诉我。感谢。

这是playlist.component.ts文件

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);
}

}

这是playlist.component.html文件

<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>

这是app.component.ts文件

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 个答案:

答案 0 :(得分:1)

您正在尝试使用未定义的变量。

您已声明了这些参数:

 /**
    Provides a public method to call to exchange an access token for an
    updated access token with updated data encoded in it. This method
    essentially asks the backend to update an access token with different
    values. This is, at the moment, is only used to switch the company root
    attribute in the token (AKA switch companies for admins).

    @param {string} token - The valid access token
    @param {object} [headers] - An optional object which can add additional
    headers to the request

    @param {object} additionalData - An object which contains the data which should be updated on the token. It should look  something like this:
    ```
    {
        company_root_id: '<UUID of a valid company root>'
    }
    ```
    @return {Promise} A promise which is the request. It will either resolve
    with the updated session data or reject with the error.
  */
 exchangeAccessToken(token, headers, additionalData) {
     const data = this.makeRefreshData(token);
     Ember.merge(data, additionalData);

     return new Ember.RSVP.Promise((resolve, reject) => {
         this.makeRequest(this.serverTokenRefreshEndpoint, data, headers).then(response => {
             Ember.run(() => {
                 try {
                     const sessionData = this.handleAuthResponse(response);

                     this.trigger('sessionDataUpdated', sessionData);
                     resolve(sessionData);
                 } catch(error) {
                     reject(error);
                 }
             });
         }, (xhr, status, error) => {
             Ember.Logger.warn(`Access token could not be refreshed - server responded with ${error}.`);
             reject();
         });
     });
 }

你还需要声明你的'div'。

 switchCompany(companyId) {
     let session = this.get('_session.session');

     if(!this.get('isAdministrator')) {
         throw new Error('Logged in user is not an administrator, they cannot switch companies.');
     }

     let token = session.get('authenticated.access_token');
     let appInstance = Ember.getOwner(this);
     let authorizerName = session.get('authenticator');
     let authorizer = appInstance.lookup(authorizerName);
     if(!authorizer) {
         throw new Error(`Authorizer (${authorizerName}) does not exist`);
     }
     if(typeof authorizer.exchangeAccessToken !== 'function') {
         throw new Error(`Authorizer (${authorizerName}) does not have an \`exchangeAccessToken\` method.`);
     }
     return authorizer.exchangeAccessToken(token, null, {
         company_root_id: companyId
     });
 }

但请注意,您没有定义任何“div”。