कोणीय में एक टेम्पलेट में एक चर घोषित करने के लिए कैसे


200

मेरे पास निम्नलिखित टेम्पलेट हैं:

<div>
  <span>{{aVariable}}</span>
</div>

और के साथ समाप्त करना चाहते हैं:

<div "let a = aVariable">
  <span>{{a}}</span>
</div>

क्या कोई तरीका है?


Im यह जानने के लिए इच्छुक है कि इस उदाहरण जैसे बाध्यकारी पैरामीटर का नाम बदलने के लिए क्या आवश्यकता / उपयोग का मामला है?
LDJ

29
यह सिर्फ टैब [तत्व] की तरह कुछ को रोकने के लिए है। उदाहरण के लिए। मुझे पता है कि मैं घटक में समस्या को हल कर सकता हूं, लेकिन मैं सिर्फ यह देख रहा था कि टेम्पलेट में कैसे करना है (भले ही मैं उस समाधान के साथ समाप्त न हो)।
स्लीपियन जूल

2
@LDJ एक नमूना उपयोग मामला: दक्षता। Stackblitz.com/angular/… <mat-checkbox [ check ] = "descendantsAllSelected (नोड)" [indeterminate] = "descendantsPartiallySelected (नोड) (बदलें) =" todoItemSelectionToggle (नोड) "{नोड} के नमूने का उपयोग करें । आइटम}} </ mat-checkbox> वास्तव में वंशजपार्टीलीसेलेक्टेड () कॉल वंशजअनुकूलित ()। इसका मतलब है कि कुछ समय के वंशज सभी चुने हुए दो बार कहलाते हैं। यदि कोई स्थानीय चर है, तो इससे बचा जा सकता है।
Steven.Xi

3
<div *ngIf="{name:'john'} as user1; let user"> <i>{{user1|json}}</i> <i>{{user|json}}</i> </div>
dasfdsa

@dasfdsa मेरा मानना है कि user1 === user, इस प्रकार आप किसी भी कार्य *ngIf="{name:'john'} as user1या *ngIf="{name:'john'};let userमें के रूप में yurzui का जवाब
CPHPython

जवाबों:


173

अपडेट करें

हम सिर्फ निर्देश बना सकते हैं *ngIfऔर इसे कॉल कर सकते हैं*ngVar

एनजी-var.directive.ts

@Directive({
    selector: '[ngVar]',
})
export class VarDirective {
  @Input()
  set ngVar(context: any) {
    this.context.$implicit = this.context.ngVar = context;
    this.updateView();
  }

  context: any = {};

  constructor(private vcRef: ViewContainerRef, private templateRef: TemplateRef<any>) {}

  updateView() {
    this.vcRef.clear();
    this.vcRef.createEmbeddedView(this.templateRef, this.context);
  }
}

इस *ngVarनिर्देश के साथ हम निम्नलिखित का उपयोग कर सकते हैं

<div *ngVar="false as variable">
      <span>{{variable | json}}</span>
</div>

या

<div *ngVar="false; let variable">
    <span>{{variable | json}}</span>
</div>

या

<div *ngVar="45 as variable">
    <span>{{variable | json}}</span>
</div>

या

<div *ngVar="{ x: 4 } as variable">
    <span>{{variable | json}}</span>
</div>

प्लंकर उदाहरण Angular4 ngVar

यह सभी देखें

मूल उत्तर

कोणीय v4

1) div+ ngIf+let

<div *ngIf="{ a: 1, b: 2 }; let variable">
  <span>{{variable.a}}</span>
  <span>{{variable.b}}</span>
</div>

2) div+ ngIf+as

राय

<div *ngIf="{ a: 1, b: 2, c: 3 + x } as variable">
  <span>{{variable.a}}</span>
  <span>{{variable.b}}</span>
  <span>{{variable.c}}</span>
</div>

component.ts

export class AppComponent {
  x = 5;
}

3) यदि आप रैपर नहीं बनाना चाहते हैं जैसे divआप उपयोग कर सकते हैंng-container

राय

<ng-container *ngIf="{ a: 1, b: 2, c: 3 + x } as variable">
  <span>{{variable.a}}</span>
  <span>{{variable.b}}</span>
  <span>{{variable.c}}</span>
</ng-container>

जैसा कि @ कीथ ने टिप्पणियों में उल्लेख किया है

यह ज्यादातर मामलों में काम करेगा लेकिन यह एक सामान्य समाधान नहीं है क्योंकि यह परिवर्तनशील सत्य पर निर्भर करता है

अन्य दृष्टिकोण के लिए अद्यतन देखें।


10
यह ज्यादातर मामलों में काम करेगा लेकिन यह एक सामान्य समाधान नहीं है क्योंकि यह variableसत्य होने पर निर्भर करता है
कीथ

6
@Keith इसे इंगित करने के लिए धन्यवाद। आप मेरे अद्यतन उत्तर पर एक नज़र डाल सकते हैं
yurzui

3
यह नया उत्तर होना चाहिए क्योंकि यह 1) अन्य समाधान की तुलना में अधिक आधुनिक है 2) वर्तमान उत्तर में जुड़े पुल अनुरोधों को सारांशित करता है और बहुत समय बचाता है 3) बाहरी लिंक के बजाय उदाहरण इनलाइन शामिल हैं। यह दिखाने के लिए धन्यवाद। AFAIK में लिपटी कोई भी वस्तु {}सत्यता का मूल्यांकन करेगी, इसलिए यह समाधान काफी मजबूत है।
kvanberendonck

4
उदाहरण के लिए, विस्तार योग्य बटन: *ngIf="{ expanded: false } as scope"और फिर अगर आप बूटस्ट्रैप का उपयोग कर रहे हैं, तो आप बस उपयोग कर सकते हैं [ngClass]="{ 'in': scope.expanded }"और (click)="scope.expanded = !scope.expanded"इसके बजाय अपनी js/ tsफ़ाइलों में कुछ भी जोड़ सकते हैं।
kvanberendonck

1
संबंधित गितुब अंक ( *ngIfकस्टम एनवार सामान के बजाय एक सरल का उपयोग करते हुए अंक ): github.com/angular/angular/issues/14985
phil294

80

बदसूरत, लेकिन:

<div *ngFor="let a of [aVariable]">
  <span>{{a}}</span>
</div>

जब async पाइप के साथ प्रयोग किया जाता है:

<div *ngFor="let a of [aVariable | async]">
  <span>{{a.prop1}}</span>
  <span>{{a.prop2}}</span>
</div>

4
वह जो मैं सहज *ngFor="let a of [(someStream$ | async).someA]रूप से आया था - वह भी उसी के साथ काम करता है । मुझे लगता है कि <ng-container>यह एक बहुत ही सही काम करता है के साथ प्रयोग किया जाता है !
एंजेलोस पिकुलास

1
के मामले में *ngFor, ध्यान रखें कि जब तक आप किसी trackByफ़ंक्शन को निर्दिष्ट नहीं करते जो सभी मानों के लिए समान आईडी देता है , तब तक सभी नेस्टेड सामग्री को फिर से बनाया जाएगा ।
वेलेरी कटकोव

74

आप templateAngular 2 में या ng-templateAngular 4+ में एक तत्व का उपयोग करके HTML कोड में चर घोषित कर सकते हैं ।

टेम्प्लेट में एक संदर्भ वस्तु होती है, जिसके गुणों को letबाध्यकारी सिंटैक्स का उपयोग करके चर को सौंपा जा सकता है । ध्यान दें कि आपको टेम्पलेट के लिए एक आउटलेट निर्दिष्ट करना होगा, लेकिन यह अपने आप में एक संदर्भ हो सकता है।

<ng-template let-a="aVariable" [ngTemplateOutletContext]="{ aVariable: 123 }" [ngTemplateOutlet]="selfie" #selfie>
  <div>
    <span>{{a}}</span>
  </div>
</ng-template>

<!-- Output
<div>
  <span>123</span>
</div>
-->

आप $implicitकस्टम ऑब्जेक्ट के बजाय संदर्भ ऑब्जेक्ट की संपत्ति का उपयोग करके कोड की मात्रा को कम कर सकते हैं।

<ng-template let-a [ngTemplateOutletContext]="{ $implicit: 123 }" [ngTemplateOutlet]="t" #t>
  <div>
    <span>{{a}}</span>
  </div>
</ng-template>

संदर्भ वस्तु एक शाब्दिक वस्तु या कोई अन्य बाध्यकारी अभिव्यक्ति हो सकती है। यहां तक ​​कि पाइप को कोष्ठक से घिरे होने पर काम करने लगता है।

के मान्य उदाहरण ngTemplateOutletContext:

  • [ngTemplateOutletContext]="{ aVariable: 123 }"
  • [ngTemplateOutletContext]="{ aVariable: (3.141592 | number:'3.1-5') }"
  • [ngTemplateOutletContext]="{ aVariable: anotherVariable }" साथ उपयोग let-a="aVariable"
  • [ngTemplateOutletContext]="{ $implicit: anotherVariable }" साथ उपयोग let-a
  • [ngTemplateOutletContext]="ctx"जहां ctxएक सार्वजनिक संपत्ति है

इसे काम करने के लिए मुझे आपका कोड '<टेम्पलेट ...' से '<ng-टेम्पलेट ...' में बदलना होगा।
हम्पाकरीसाज

2
हां, आप केवल <template>Angular 2 में उपयोग कर सकते हैं । आप <template>या तो <ng-template>Angular 4 में उपयोग कर सकते हैं , लेकिन आपको केवल उपयोग करना चाहिए <ng-template>। कोणीय 5 के लिए समर्थन गिरा दिया <template>
स्टीवन लाइकेन

किसलिए है t?
मटका

1
@matttm #tएक टेम्पलेट वैरिएबल है जो स्टोर करता है ng-template। इसका उपयोग [ngTemplateOutlet]="t"एनजी-टेम्पलेट संदर्भ को स्वयं बनाने के लिए किया जाता है।
स्टीवन लाइकेन्स

यह विचित्र है, लेकिन यह काम करता है! कोणीय को यह सरल बनाना चाहिए, एक अंतर्निहित चर निर्देश के साथ। धन्यवाद।
तेतरदेव

57

अद्यतन ३

अंक 2451 को कोणीय 4.0.0 में तय किया गया है

यह सभी देखें

अद्यतन २

यह समर्थित नहीं है।

टेम्पलेट वैरिएबल हैं, लेकिन यह मनमाना मान निर्दिष्ट करने के लिए समर्थित नहीं है। उनका उपयोग केवल उन तत्वों को संदर्भित करने के लिए किया जा सकता है जिन्हें वे लागू होते हैं, निर्देशों या घटकों के निर्यात किए गए नाम और संरचनात्मक निर्देशों के लिए गुंजाइश चर जैसेngFor ,

यह सभी देखें Https://github.com/angular/angular/issues/2451 देखें

अपडेट १

@Directive({
  selector: '[var]',
  exportAs: 'var'
})
class VarDirective {
  @Input() var:any;
}

और इसे इनिशियलाइज़ करें

<div #aVariable="var" var="abc"></div>

या

<div #aVariable="var" [var]="'abc'"></div>

और जैसे चर का उपयोग करें

<div>{{aVariable.var}}</div>

(टेस्ट नहीं हुआ)

  • #aVariable का संदर्भ बनाता है VarDirective( exportAs: 'var') के
  • var="abc" तात्कालिकता VarDirective और स्ट्रिंग मान "abc"को इसके मूल्य इनपुट से गुजरता है ।
  • aVariable.varvarनिर्देश varइनपुट को निर्दिष्ट मान पढ़ता है ।

क्या ऐसा करने के लिए एक संरचनात्मक निर्देश बनाना संभव नहीं होगा?
स्काइपियन जूल

यदि आपको बार-बार इसकी आवश्यकता है तो एक निर्देश वह कर सकता है जो आप चाहते हैं। एक संरचनात्मक निर्देश यह स्वयं का दृष्टिकोण बनाता है, यह संभवतः वह नहीं है जो आप चाहते हैं।
गुंटर ज़ोचबॉयर

1
@ गुंटरेज़ोचबॉएर, बहुत अच्छा सामान। मुझे पता है कि इसकी शायद एक बेहतर प्रथा है कि component.tsफ़ाइल में गणना की गई / तैयार की गई है। लेकिन मेरे लिए यह इतना आसान है कि मैं कुछ मामलों के लिए एक सिंकिंग योजना के कारण उन्हें अपने ऐप में लागू कर रहा हूं। मैं जावास्क्रिप्ट संदर्भ नियमों का लाभ उठा रहा हूं जब विभिन्न चर एक ही वस्तु की ओर इशारा करते हैं।
अम्मारसीएसई

मुझे एक त्रुटि मिल रही है There is no directive with "exportAs" set to "var"। क्या कोई मुझे बता सकता है कि मैंने क्या गलती की? मैंने उपरोक्त निर्देश का उपयोग किया है।
पार्थ सारथी घोष

शायद आपने करने declarations: [...]के लिए निर्देश नहीं जोड़ा था @NgModule()। यदि यह समस्या नहीं है, तो कृपया एक नया प्रश्न बनाएं और कोड प्रदान करें जो समस्या का निदान करने की अनुमति देता है।
गुंटर ज़ोचबॉयर

12

मैं यह सुझाव दूंगा: https://medium.com/@AustinMatherne/angular-let-directive-a168d4248138

यह निर्देश आपको कुछ लिखने की अनुमति देता है:

<div *ngLet="'myVal' as myVar">
  <span> {{ myVar }} </span>
</div>

1
इस तरह से लेकिन * संरचनात्मक निर्देशों के लिए आरक्षित है, जो कि यह नहीं है, वैसे भी +1
danday74

11

यहाँ एक निर्देश मैंने लिखा है कि एक्सपोर्टर्स डेकोरेटर पैरामीटर के उपयोग पर विस्तार करता है, और आपको एक स्थानीय चर के रूप में एक शब्दकोश का उपयोग करने की अनुमति देता है।

import { Directive, Input } from "@angular/core";
@Directive({
    selector:"[localVariables]",
    exportAs:"localVariables"
})
export class LocalVariables {
    @Input("localVariables") set localVariables( struct: any ) {
        if ( typeof struct === "object" ) {
            for( var variableName in struct ) {
                this[variableName] = struct[variableName];
            }
        }
    }
    constructor( ) {
    }
}

आप इसे एक टेम्पलेट में निम्नानुसार उपयोग कर सकते हैं:

<div #local="localVariables" [localVariables]="{a: 1, b: 2, c: 3+2}">
   <span>a = {{local.a}}</span>
   <span>b = {{local.b}}</span>
   <span>c = {{local.c}}</span>
</div>

बेशक #local कोई भी मान्य स्थानीय चर नाम हो सकता है।


के रूप में एक 'उत्पादन' निर्माण पास नहीं है (यह भी आईडीई द्वारा त्रुटियों के रूप में दिखाता है)। इस के आसपास पाने [key: string]: any;के Classलिए जोड़ें ।
चार्ली

7

यदि आप किसी फ़ंक्शन की प्रतिक्रिया प्राप्त करना चाहते हैं और इसे एक चर में सेट करना चाहते हैं, तो आप टेम्पलेट ng-containerको संशोधित करने से बचने के लिए इसका उपयोग टेम्पलेट में निम्नलिखित की तरह कर सकते हैं ।

<ng-container *ngIf="methodName(parameters) as respObject">
  {{respObject.name}}
</ng-container>

और घटक में विधि कुछ इस तरह हो सकती है

methodName(parameters: any): any {
  return {name: 'Test name'};
}

5

यदि आपको कोणीय भाषा सेवा से अपने टेम्प्लेट में भीतर से स्वत: पूर्ण समर्थन की आवश्यकता है :

तुल्यकालिक:

myVar = { hello: '' };

<ng-container *ngIf="myVar; let var;">
  {{var.hello}}
</ng-container>

Async पाइप का उपयोग करना:

myVar$ = of({ hello: '' });

<ng-container *ngIf="myVar$ | async; let var;">
  {{var.hello}}
</ng-container>

2

यह बहुत सरल है, अतिरिक्त कुछ भी करने की आवश्यकता नहीं है। मेरे उदाहरण में मैं चर "ओपन" घोषित करता हूं और फिर इसका उपयोग करता हूं।

   <mat-accordion class="accord-align" #open>
      <mat-expansion-panel hideToggle="true" (opened)="open.value=true" (closed)="open.value=false">
        <mat-expansion-panel-header>
          <span class="accord-title">Review Policy Summary</span>
          <span class="spacer"></span>
          <a *ngIf="!open.value" class="f-accent">SHOW</a>
          <a *ngIf="open.value" class="f-accent">HIDE</a>
        </mat-expansion-panel-header>
        <mat-divider></mat-divider>
        <!-- Quote Details Component -->
        <quote-details [quote]="quote"></quote-details>
      </mat-expansion-panel>
    </mat-accordion>

आप एक टैग का नामकरण कर रहे हैं, यह परिवर्तनशील घोषित नहीं कर रहा है
Amirreza

1
@Arereza, सटीक होने के लिए मैं एक मूल्य को स्टोर करने के लिए ElementRef का उपयोग कर रहा हूं।
जैक रस्स

बहुत बढ़िया! मुझे इसका उपयोग करना पड़ा "?"क्योंकि मेरे पास "आइडेंटिफायर 'वैल्यू' 'जैसा संदेश" परिभाषित नहीं है "= =" खुला है। "
ए। मोरेल

2

मैं कोणीय 6x का उपयोग कर रहा हूं और नीचे स्निपेट का उपयोग करके समाप्त हो गया हूं। मेरे पास एक scenerio है जहाँ मुझे उपयोगकर्ता को किसी कार्य ऑब्जेक्ट से खोजना है। इसमें उपयोगकर्ताओं की सरणी है लेकिन मुझे असाइन किए गए उपयोगकर्ता को चुनना है।

<ng-container *ngTemplateOutlet="memberTemplate; context:{o: getAssignee(task) }">
</ng-container>
<ng-template #memberTemplate let-user="o">
  <ng-container *ngIf="user">
    <div class="d-flex flex-row-reverse">
      <span class="image-block">
        <ngx-avatar placement="left" ngbTooltip="{{user.firstName}} {{user.lastName}}" class="task-assigned" value="28%" [src]="user.googleId" size="32"></ngx-avatar>
      </span>
    </div>
  </ng-container>
</ng-template>

1

मुझे ऐसा करने के लिए एक निर्देश बनाने का दृष्टिकोण पसंद आया (अच्छा कॉल @yurzui)।

मैंने एक मीडियम आर्टिकल कोणीय "लेट" डायरेक्टिव ढूंढ कर समाप्त किया, जो इस समस्या को अच्छी तरह से समझाता है और एक कस्टम लेट डायरेक्टिव का प्रस्ताव करता है जो न्यूनतम कोड परिवर्तन के साथ मेरे उपयोग के मामले के लिए शानदार काम कर रहा है।

यहां मेरे संशोधनों के साथ जिस्ट (पोस्टिंग के समय) है:

import { Directive, Input, TemplateRef, ViewContainerRef } from '@angular/core'

interface LetContext <T> {
  appLet: T | null
}

@Directive({
  selector: '[appLet]',
})
export class LetDirective <T> {
  private _context: LetContext <T> = { appLet: null }

  constructor(_viewContainer: ViewContainerRef, _templateRef: TemplateRef <LetContext <T> >) {
    _viewContainer.createEmbeddedView(_templateRef, this._context)
  }

  @Input()
  set appLet(value: T) {
    this._context.appLet = value
  }
}

मेरे मुख्य परिवर्तन थे:

  • उपसर्ग को 'एनजी' से 'ऐप' में बदलना (आपको अपने ऐप के कस्टम उपसर्ग जो भी हो, का उपयोग करना चाहिए)
  • बदल रहा appLet: TहैappLet: T | null

यह निश्चित नहीं है कि कोणीय टीम ने सिर्फ आधिकारिक एनग्लैट निर्देश नहीं बल्कि व्हाट्सएप बनाया है।

मूल स्रोत कोड क्रेडिट @AustinMatherne पर जाता है


यह पेज पर मेरा पसंदीदा दृष्टिकोण था और इसने मेरे लिए काम किया।
स्किचन

1

छोटा जवाब जो किसी की मदद करे

  • टेम्प्लेट संदर्भ चर अक्सर टेम्पलेट के भीतर DOM तत्व का संदर्भ देता है।
  • कोणीय या वेब घटक और निर्देश का भी संदर्भ।
  • इसका मतलब है कि आप एक टेम्पलेट में कहीं भी आसानी से भिन्न को एक्सेस कर सकते हैं

यहां छवि विवरण दर्ज करें

यहां छवि विवरण दर्ज करें

  • हैश प्रतीक (#) का उपयोग करके संदर्भ चर घोषित करें
  • एक चर को एक घटना पर एक पैरामीटर के रूप में पारित करने में सक्षम हो सकता है

यहां छवि विवरण दर्ज करें

  show(lastName: HTMLInputElement){
    this.fullName = this.nameInputRef.nativeElement.value + ' ' + lastName.value;
    this.ctx.fullName = this.fullName;
  }

* हालांकि, आप अपने घटक के अंदर इसे देखने के लिए ViewChild डेकोरेटर का उपयोग कर सकते हैं।

import {ViewChild, ElementRef} from '@angular/core';

संदर्भ पहले घटक के अंदर पहला नामांकित संस्करण

@ViewChild('firstNameInput') nameInputRef: ElementRef;

उसके बाद, आप अपने Component के अंदर कहीं भी इस .nameInputRef का उपयोग कर सकते हैं।

एनजी-टेम्पलेट के साथ काम करना

एनजी-टेम्प्लेट के मामले में, यह थोड़ा अलग है क्योंकि प्रत्येक टेम्प्लेट का इनपुट चर का अपना सेट होता है।

यहां छवि विवरण दर्ज करें

https://stackblitz.com/edit/angular-2-template-reference-variable


0

उन लोगों के लिए जिन्होंने एक प्रतिस्थापन के रूप में एक संरचनात्मक निर्देश का उपयोग करने का निर्णय लिया *ngIf, ध्यान रखें कि निर्देश संदर्भ डिफ़ॉल्ट रूप से जाँच नहीं किया गया है। एक प्रकार का सुरक्षित निर्देश बनाने के लिए ngTemplateContextGuardसंपत्ति को जोड़ा जाना चाहिए, निर्देश के संदर्भ को टाइप करना देखें । उदाहरण के लिए:

import { Directive, Input, TemplateRef, ViewContainerRef } from '@angular/core';

@Directive({
    // don't use 'ng' prefix since it's reserved for Angular
    selector: '[appVar]',
})
export class VarDirective<T = unknown> {
    // https://angular.io/guide/structural-directives#typing-the-directives-context
    static ngTemplateContextGuard<T>(dir: VarDirective<T>, ctx: any): ctx is Context<T> {
        return true;
    }

    private context?: Context<T>;

    constructor(
        private vcRef: ViewContainerRef,
        private templateRef: TemplateRef<Context<T>>
    ) {}

    @Input()
    set appVar(value: T) {
        if (this.context) {
            this.context.appVar = value;
        } else {
            this.context = { appVar: value };
            this.vcRef.createEmbeddedView(this.templateRef, this.context);
        }
    }
}

interface Context<T> {
    appVar: T;
}

निर्देश का उपयोग ऐसे ही किया जा सकता है *ngIf, सिवाय इसके कि यह गलत मूल्यों को संग्रहीत कर सकता है :

<ng-container *appVar="false as value">{{value}}</ng-container>

<!-- error: User doesn't have `nam` property-->
<ng-container *appVar="user as user">{{user.nam}}</ng-container>

<ng-container *appVar="user$ | async as user">{{user.name}}</ng-container>

इसकी तुलना में एकमात्र दोष यह *ngIfहै कि कोणीय भाषा सेवा परिवर्तनशील प्रकार का पता नहीं लगा सकती है, ताकि टेम्प्लेट में कोई कोड पूरा न हो। मुझे उम्मीद है कि इसे जल्द ही ठीक कर लिया जाएगा।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.