2012-10-07 48 views
7

:imprenta contexto equivocado este Código

export class ViewModel { 
     public users: knockout.koObservableArrayBase; 

     constructor() { 
      this.users = ko.observableArray([]); 
      this.removeUser = this.removeUser.bind(this);//<-- Here compiller shows error 
     } 

     removeUser(user: User): void { 
      this.users.remove(user); 
     } 
} 

HTML:

<table> 
    <thead> 
     <tr> 
      <th>Name</th> 
      <th>Surname</th> 
     </tr> 
    </thead> 
    <tbody data-bind="foreach: users"> 
     <tr> 
      <td><a href="#" data-bind="click: $root.removeUser">Remove</a></td> 
      <td data-bind="text: name"></td> 
      <td data-bind="text: surname"></td> 
     </tr> 
    </tbody> 
</table> 

El problema es que en el método removeuser. De forma predeterminada, si no enlace el contexto, esto == UserToDelete - no viewOl objeto objeto. Si agrego al constructor: this.removeUser = this.removeUser.bind(this); (manually enforce context), entonces el contexto es necesario como este == viewmodel, pero luego TypeScript se queja por "No se puede convertir la función a (usuario: Usuario) => void requiere una firma de llamada, pero la función carece de una."

+0

Si no te importa HTML desordenado esta es una alternativa: Remove

Respuesta

5

No conozco ko, quizás haya una forma mejor de resolver el cambio de contexto, pero el error del compilador mecanografiado es causado por 'bind' devolver tipo 'Function' que es incompatible con el tipo 'removeUser' . Usted debe ser capaz de resolver esto mediante la fundición de la función devuelta a la firma de tipo original, de la siguiente manera:

this.removeUser = <(user: User) => void> this.removeUser.bind(this); 
2

Bueno, yo tenía el mismo problema es por eso que ocurrió la siguiente clase base para arreglar mi problema

export class ViewModelBase { 
    private prefix: string = 'On'; 

    public Initialize() { 
     for (var methodName in this) { 
      var fn = this[methodName]; 
      var newMethodName = methodName.substr(this.prefix.length); 
      if (typeof fn === 'function' && methodName.indexOf(this.prefix) == 0 && this[newMethodName] == undefined) { 
       this[newMethodName] = $.proxy(fn, this); 
      } 
     } 
    } 
} 

lo que hace esto es repetir todos los miembros de su clase y si un método comienza con On, creará un nuevo método sin On que llamará al método original con el contexto correcto.

No es que $.proxy es una llamada jquery, por lo que se necesita jquery para que funcione.

1

Bueno, la solución más simple y lo que normalmente hago con js mecanografiado y nocaut es que no declaro funciones llamadas de knockout en el prototipo sino en el constructor. Entonces, lo haría así:

export class ViewModel { 
     public users: knockout.koObservableArrayBase; 
     removeUser:(user: User) => void; 

     constructor() { 
      this.users = ko.observableArray([]); 
      this.removeUser = (user:User) => { 
       this.users.remove(user); 
      } 
     } 
} 
0

Me encontré con el mismo problema. Para obtener el contexto correcto, puede usar los parámetros que pasan mediante el enlace de clic. El enlace de enlace pasa 2 parámetros, es decir, el usuario y el evento jquery del clic.

Si toma el evento jquery y utiliza la función ko.contextFor(), puede obtener el contexto correcto.

Su función sería algo como:

removeUser(user: User, clickEvent: any): void { 
    var self = ko.contextFor(clickEvent.srcElement).$root; 
    self.users.remove(user); 
} 
2

Una alternativa es cambiar la unión de usar bind función de JavaScript para forzar el valor de this ser su modelo de vista clic: data-bind="click: $root.MyFunc.bind($root)".

Tenga en cuenta que $data y el objeto clic event todavía se pasarán como argumentos a MyFunc de Knockout como se describe en la especificación click binding. Si necesita anular los argumentos que pasan a MyFunc, simplemente páselos a la función de vinculación después de $root, haga lo siguiente: .bind($root, param1, param2). Técnicamente, estos argumentos serán anteponiendo a los argumentos suministrados por Knockout, dando argumentos [param1, param2, data, event].

Cuestiones relacionadas