I've been going down the long road of learning Angular recently, and I love it and want to learn more, but I have a couple naive newbie questions whose answers I thought should be obvious, but I haven't been able to figure out:<p>Is there a standard way to define local variables in an Angular template so you don't have to repeat the same redundant expression again and again (or so you can at least give an expression a self documenting variable name so it's not so mysterious)? Or do you have to define an instance variable on your component and figure out how to initialize it to the right value before the template gets executed, with no way to lazily (or repeatedly) evaluate it by putting the calculation inside conditionals (or loops) in the template so they're not run if they're not needed (or to calculate the local variables independently for every loop iteration)? Is there an angular hook or technique that's meant for that, and efficient, and hopefully doesn't involve much arbitrary non-JavaScript gobbledygook syntax, and is at least somewhat standard and well supported? Please don't tell me I shouldn't ever want to do that for some reason of ideological purity or separation of concerns (as if a templating language could ever be called "pure" or "elegant"). The common legitimate use case is ngIf="some expression is not null" then {{some expression}}, and also ngIf="some expressions" ... ngIf="not some expression".<p>I googled for it, and the solutions of "abuse ngIf's special goofy syntax to name the result of the condition and pray to God it's truthy or don't bother" and "abuse ngFor to loop over an array of one item to give it a name" are not acceptable answers. There were also a few competing and possibly out-of-date "install this non-standard ngLet directive that I hacked up but don't support, but don't call it with an "ng" prefix because that's reserved for the Angular team" -- but isn't there a standard way of doing such a simple essential thing, that the Angular team already thought of and included, such that other people will have some clue what's going on when they see it? And it would be nice to be able to define more than one variable at once per begin/end tag, if you know what I mean. Maybe even without using any begin/end tags, perchance to dream?<p>Also, is there a way to easily define simple light weight macros ("snippet reuse") so you can repeat the same pattern in one or more components, without defining a whole component in all its glory and splendor with multiple files that other multiple files need to import and declare? Or even a global file of shared macros that a bunch of other templates can import, like the globally shared css declarations you can include in local css files? I've seen "ng-template", but I am having a hard time getting my head around it, compared to the simplicity and power of Genshi's py:match, that's based on xpath, and py:def, that precisely follows Python function calling conventions and that you can easily call from any normal expression. And py:match is quite useful for defining concise custom tags (or xpath patterns) that can wrap embedded content. In comparison, ng-templates seems quite clumsy and limited, and confusing about calling and scoping and passing parameters and content, which is nothing like standard JavaScript calling conventions, and reminds me more of the abomination that is Zope METAL templates.<p><a href="https://zope.readthedocs.io/en/latest/zopebook/AppendixC.html#metal-overview" rel="nofollow">https://zope.readthedocs.io/en/latest/zopebook/AppendixC.htm...</a><p><a href="https://en.wikipedia.org/wiki/Template_Attribute_Language#METAL" rel="nofollow">https://en.wikipedia.org/wiki/Template_Attribute_Language#ME...</a><p><a href="https://en.wikipedia.org/wiki/Zope#Zope_Page_Templates" rel="nofollow">https://en.wikipedia.org/wiki/Zope#Zope_Page_Templates</a><p>I've been using and loving Genshi with Python for more than a decade (and before that, Kid, which Genshi is almost the same as, and before that Zope page templates, TAL, and METAL templates, which inspired Kid and Genshi, but totally sucked), and I love its ability to drop into Python with <?python ... ?> to define some variables or import some functions locally in the template that you can use, with real honest to god multi-line indented Python "if" statements for logic (and Python comments for, err, commenting) instead of Christmas trees of deeply nested ternary ? : operators (or rather postfix conditional "foo if bar else baz" Python expressions). Genshi also has "with" for defining scoped local variables with tags, like <py:with vars="y=7; z=x+10">$x $y $z</py:with>.<p>And I also love Genshi's py:def for making locally defined or libraries of includable imperative "code snippet" templates you can call just like Python functions (with glorious optional named defaulting args, etc), and py:match for declaring xpath pattern matching templates that can wrap html content as a parameter (so the macro can cherry-pick out and transform different parts of the passed content with xpath), as well as taking attribute parameters.<p>Another nice feature of Genshi is that for all directives it supports both the attribute form like <div py:if="condition"> ... </div> attached to an element that you want to keep, or the element form that dissolves without leaving an element, like <py:if test="condition"> ... </py:if> . You can also attach multiple directive attributes to the same element, thanks to the way it executes them in a well defined ordered hierarchy that makes practical sense (like "for" above "if", so each iteration of the "for" loop can be conditionalized with its own "if" evaluation), and "def" above all else, so you can define a single tag macro that loops over something then conditionalizes each iteration, then sets attributes on and adds content to the included elements. It's quite concise and expressive!<p><div py:def="FizzBusted(count)" py:for="i in range(count)" py:if="i % 3" py:attrs="{'class': 'orange' if i % 7 &lt; 2 else 'blue'}" py:content="['odd', 'even'][i%2]"/><p><a href="https://genshi.edgewall.org/" rel="nofollow">https://genshi.edgewall.org/</a><p><a href="https://genshi.edgewall.org/wiki/Documentation/xml-templates.html" rel="nofollow">https://genshi.edgewall.org/wiki/Documentation/xml-templates...</a><p>py:def<p><a href="https://genshi.edgewall.org/wiki/Documentation/xml-templates.html#id4" rel="nofollow">https://genshi.edgewall.org/wiki/Documentation/xml-templates...</a><p>py:match<p><a href="https://genshi.edgewall.org/wiki/Documentation/xml-templates.html#id5" rel="nofollow">https://genshi.edgewall.org/wiki/Documentation/xml-templates...</a><p>Processing order of multiple attributes (precedence rules you must remember, but they make practical sense, and at least Genshi is quite minimal and only has a few directives):
py:def
py:match
py:when
py:otherwise
py:for
py:if
py:choose
py:with
py:replace
py:content
py:attrs
py:strip<p><a href="https://genshi.edgewall.org/wiki/Documentation/xml-templates.html#processing-order" rel="nofollow">https://genshi.edgewall.org/wiki/Documentation/xml-templates...</a><p>These two features (local variables and code snippets) are so important to me, and I'm having such a hard time figuring out how to do them in Angular, that I feel like there's whole a chapter in the Angular templating manual that I missed somehow. Thanks for any tips on how to do this kind of stuff with Angular templates!<p>I've written more opinions about Genshi and templating on hn before:<p><a href="https://news.ycombinator.com/item?id=8445252" rel="nofollow">https://news.ycombinator.com/item?id=8445252</a><p><a href="https://news.ycombinator.com/item?id=10842990" rel="nofollow">https://news.ycombinator.com/item?id=10842990</a><p><a href="https://news.ycombinator.com/item?id=12365442" rel="nofollow">https://news.ycombinator.com/item?id=12365442</a><p><a href="https://news.ycombinator.com/item?id=12527839" rel="nofollow">https://news.ycombinator.com/item?id=12527839</a><p><a href="https://news.ycombinator.com/item?id=16677520" rel="nofollow">https://news.ycombinator.com/item?id=16677520</a><p><a href="https://news.ycombinator.com/item?id=20745676" rel="nofollow">https://news.ycombinator.com/item?id=20745676</a><p><a href="https://news.ycombinator.com/item?id=10842902" rel="nofollow">https://news.ycombinator.com/item?id=10842902</a>