Skip to content

Allow evaluation of a detached buffer in a specified context (angular2 templates) #5470

Description

@alexeagle

Angular/Typescript teams discussed this in person.

Angular 2 includes a template parser, and an expression language which may be used in places in the template.
We would like to translate the template to a TypeScript buffer, and pass the buffer to the language services for things like producing semantic errors, requesting intellisense, and the other usual editor features.
However, the template has a backing class (actually a virtual class per Tobias Bosch (@tbosch) ) where the fields may be referenced by template expressions. In our canonical example,

@Component({selector: 'greet', template: 'Hello {{name}}!'})
 class Greet {
   name: string;
   constructor() {
     this.name = 'World';
   }
 }

The template could be represented in TypeScript with the expression

`Hello ${this.name}`

In order to get intellisense or errors for that expression, we need to evaluate it in a place where this.name is defined. The obvious way to do this is for us to pass a "detached buffer", meaning a range of the SourceFile which lives outside the file content. It could look like (just a wild stab at possible syntax):

__template_eval(): string { return `Hello ${this.name}`; }

as if this code existed inside the Greet class.

Also we would expect any ranges in the result to give the pos and width locations relative to the buffer we passed, not the Greet class.

Activity

  1. changed the title [-]Allow evaluation of a buffer in a specified context (angular2 templates)[/-] [+]Allow evaluation of a detached buffer in a specified context (angular2 templates)[/+] on Oct 30, 2015
  2. weswigham commented on Oct 30, 2015

    @weswigham
    Member

    Potentially duplicates #4169

  3. DanielRosenwasser commented on Nov 1, 2015

    @DanielRosenwasser
    Member

    Sounds more like #5151.

  4. alexeagle commented on Nov 2, 2015

    @alexeagle
    ContributorAuthor

    Certainly related to those, and it would be better for us to solve this in a generalizable way.
    That said, I would prefer to keep working with a specific goal in mind in this issue.

  5. added
    SuggestionAn idea for TypeScript
    Needs ProposalThis issue needs a plan that clarifies the finer details of how it could be implemented.
    on Nov 2, 2015
  6. mhegazy commented on Nov 2, 2015

    @mhegazy
    Contributor

    Bill Ticehurst (@billti) has been looking into this, we need to come up with an extensibility model for the language service that allows for non-ts file services to be provided, be it completion, goto def, find all refs, etc..

  7. billti commented on Nov 2, 2015

    @billti
    Member

    Re the above example: How does the template engine know to rewrite {{name}} as this.name? I assume it wouldn't rewrite {{Date}} as this.Date? (It's almost as though it is wrapped in a JavaScript with(this){...} block, however TypeScript doesn't support with).

    It seems as though the template engine already needs to understand some of the scoping/context from the language service, to generate the code to give back to the language service.

  8. DanielRosenwasser commented on Nov 2, 2015

    @DanielRosenwasser
    Member

    (as a minor clarification, TypeScript "supports" with, but all entities are typed as any within a with context)

  9. billti commented on Nov 2, 2015

    @billti
    Member

    "Supports" is generous. It emits valid code, but any usage gives you a build error of file1.ts(3,7): error TS2410: All symbols within a 'with' block will be resolved to 'any'.

    If you don't mind errors in your project, then yes, it's supported. 😉

  10. tbosch commented on Nov 3, 2015

    @tbosch

    So {{Date}} wouldn't work in Angular either. Adding this. before the
    expression should be safe...

    On Mon, Nov 2, 2015 at 3:43 PM Bill Ticehurst notifications@github.com
    wrote:

    "Supports" is generous. It emits valid code, but any usage gives you a
    build error of file1.ts(3,7): error TS2410: All symbols within a 'with'
    block will be resolved to 'any'.

    If you don't mind errors in your project, then yes, it's supported. [image:
    😉]

    —
    Reply to this email directly or view it on GitHub
    #5470 (comment)
    .

  11. billti commented on Nov 3, 2015

    @billti
    Member

    Ah, interesting. So in the simple case does it assume all identifiers are members on the instance?

    One area where I see this isn't safe is if I'm within a template which introduces a local, such as *ng-for='#name of items'. Now {{name}} within a nested tag refers to the introduced local, even if there is a name property on the class instance for the component.

    So it seems the expressions would need to be aware of surrounding tags and any locals they introduce, before they can assume <id> => this.<id>. Is that correct?

  12. billti commented on Nov 3, 2015

    @billti
    Member

    Actually, on re-reading the blog, can sibling elements introduce names too? e.g. player in the below:

    <video-player #player></video-player>
    <button (click)="player.pause()">Pause</button>
    

    EDIT: Adding this link as a useful reference: https://angular.io/docs/ts/latest/guide/template-syntax.html#template-expressions . Note syntax changes to "regular" JavaScript as well as "expression context".

    To circle back to the original point however: So it would seem the template engine doesn't need context from the underlying component code to understand its references and generate its code. Any identifiers it doesn't recognize (e.g. local names, $event, etc.), it will assume should be instance members (i.e. this.<id> references). Does this sound about right?

  13. mhegazy commented on May 23, 2017

    @mhegazy
    Contributor

    Alex Eagle (@alexeagle) with #12231 in place, do not think we need this issue any longer. can you please confirm?

  14. chuckjaz commented on May 24, 2017

    @chuckjaz
    Contributor

    This is no longer necessary.

  15. mhegazy commented on May 24, 2017

    @mhegazy
    Contributor

    thanks! closing.

  16. locked and limited conversation to collaborators on Jun 19, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

Needs ProposalThis issue needs a plan that clarifies the finer details of how it could be implemented.SuggestionAn idea for TypeScript

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions