Angular2 ngSwitch स्टेटमेंट में टाइपस्क्रिप्ट एनुम मान का उपयोग कैसे करें


158

टाइपस्क्रिप्ट एनम Angular2 के ngSwitch निर्देशन के साथ एक स्वाभाविक मैच लगता है। लेकिन जब मैं अपने घटक के टेम्प्लेट में एक एनम का उपयोग करने का प्रयास करता हूं, तो मुझे "अपरिभाषित ... की संपत्ति 'xxx नहीं पढ़ सकता है"। मैं अपने घटक टेम्पलेट में enum मानों का उपयोग कैसे कर सकता हूं?

कृपया ध्यान दें कि यह एक एनम (एनजीफ़ोर) के सभी मूल्यों के आधार पर HTML का चयन करने के विकल्प से अलग है। यह सवाल एनमस्विच के बारे में है जो किसी विशेष मान पर आधारित है। यद्यपि एनम के लिए एक वर्ग-आंतरिक संदर्भ बनाने का एक ही दृष्टिकोण प्रकट होता है।



1
मुझे नहीं लगता कि ये प्रश्न डुप्लिकेट हैं; दूसरा पूछ रहा है कि सभी एनुम (एनजीफ़ोर) के मूल्यों के आधार पर एचटीएमएल चुनिंदा विकल्प कैसे बनाएं, जबकि यह एक एनुमविच के बारे में है जो किसी एनम के विशेष मूल्य पर आधारित है। यद्यपि एनम के लिए एक वर्ग-आंतरिक संदर्भ बनाने का एक ही दृष्टिकोण प्रकट होता है। समानता को इंगित करने के लिए धन्यवाद।
कार्ल जी

जवाबों:


166

आप अपने कंपोनेंट क्लास में एनम का संदर्भ बना सकते हैं (मैंने केवल प्रारंभिक वर्ण को लोअर-केस में बदल दिया है) और फिर टेम्प्लेट ( प्लंकर ) से उस संदर्भ का उपयोग करें :

import {Component} from 'angular2/core';

enum CellType {Text, Placeholder}
class Cell {
  constructor(public text: string, public type: CellType) {}
}
@Component({
  selector: 'my-app',
  template: `
    <div [ngSwitch]="cell.type">
      <div *ngSwitchCase="cellType.Text">
        {{cell.text}}
      </div>
      <div *ngSwitchCase="cellType.Placeholder">
        Placeholder
      </div>
    </div>
    <button (click)="setType(cellType.Text)">Text</button>
    <button (click)="setType(cellType.Placeholder)">Placeholder</button>
  `,
})
export default class AppComponent {

  // Store a reference to the enum
  cellType = CellType;
  public cell: Cell;

  constructor() {
    this.cell = new Cell("Hello", CellType.Text)
  }

  setType(type: CellType) {
    this.cell.type = type;
  }
}

88

आप अपने घटक को जोड़ने के लिए एक कस्टम डेकोरेटर बना सकते हैं, ताकि वह एनम से अवगत हो सके।

myenum.enum.ts:

export enum MyEnum {
    FirstValue,
    SecondValue
}

myenumaware.decorator.ts

import { MyEnum } from './myenum.enum';

export function MyEnumAware(constructor: Function) {
    constructor.prototype.MyEnum = MyEnum;
}

enum-aware.component.ts

import { Component } from '@angular2/core';
import { MyEnum } from './myenum.enum';
import { MyEnumAware } from './myenumaware.decorator';

@Component({
  selector: 'enum-aware',
  template: `
    <div [ngSwitch]="myEnumValue">
      <div *ngSwitchCase="MyEnum.FirstValue">
        First Value
      </div>
      <div *ngSwitchCase="MyEnum.SecondValue">
        Second Value
      </div>
    </div>
    <button (click)="toggleValue()">Toggle Value</button>
  `,
})
@MyEnumAware // <---------------!!!
export default class EnumAwareComponent {
  myEnumValue: MyEnum = MyEnum.FirstValue;

  toggleValue() {
    this.myEnumValue = this.myEnumValue === MyEnum.FirstValue
        ? MyEnum.SecondValue : MyEnum.FirstValue;
  }
}

7
क्या किसी को एओटी संकलक के साथ इस पद्धति का उपयोग करने में सफलता मिली है?
डैनी

2
@Simon_Weaver सज्जाकार अनिवार्य रूप से फ़ंक्शन होते हैं जो फ़ंक्शन को एक पैरामीटर के रूप में लेते हैं और उस फ़ंक्शन के व्यवहार का विस्तार करते हैं। ES6 / 7 के मामले में, हम कक्षाओं के विस्तार / एनोटेशन के साथ काम कर रहे हैं। वे कैसे काम करते हैं, इस बारे में एक उच्च स्तरीय लेख यहां दिया गया है । ES7 में कार्यान्वयन का प्रस्ताव जीथब पर है - वर्तमान में चरण 2 में। उस प्रस्ताव में, वे सज्जाकारों के लिए संभावित उपयोगों पर स्पर्श करते हैं। टाइपस्क्रिप्ट, जेएस का सुपरसेट होने के नाते यह सुविधा शामिल है।
एरिक लीज

2
@Simon_Weaver इस मामले में, सिंटैक्टिक शुगर कॉल को छिपा रहा है MyEnumAware(), जहां EnumAwareComponentउदाहरण पारित किया गया है, और एक संपत्ति है, MyEnumइसके प्रोटोटाइप में जोड़ा गया है। संपत्ति का मूल्य केवल एनम सेट किया गया है। यह विधि स्वीकृत उत्तर के समान ही कार्य करती है। यह सिर्फ डेकोरेटर के लिए प्रस्तावित सिंथैटिक शुगर का फायदा उठा रहा है और टाइपस्क्रिप्ट में अनुमति दी गई है। जब आप कोणीय का उपयोग कर रहे हैं तो आप बल्ले से डेकोरेटर सिंटैक्स का उपयोग कर रहे हैं। यह वही Component है , जो एक खाली वर्ग का विस्तार है जो कोणीय के मुख्य वर्गों को पता है कि कैसे बातचीत करनी है।
एरिक लीज

5
-1: यह एओटी के साथ काम नहीं करता है, जिसके परिणामस्वरूप ERROR in ng:///.../whatever.component.html (13,3): Property 'MyEnum' does not exist on type 'EnumAwareComponent'। यह समझ में आता है, क्योंकि डेकोरेटर को जोड़ने वाली संपत्ति को कभी भी घोषित नहीं किया जाता है, जिससे टाइपस्क्रिप्ट कंपाइलर अपने अस्तित्व से अनजान रहता है।
मेरिटॉन

2
इसलिए मैं 4+ महीनों से इसका उपयोग कर रहा हूं। हालाँकि, अब जब मैं एक --prodबिल्ड (Ionic 3 / Angular 4 / Typescript 2.4.2) कर रहा हूं तो यह काम नहीं करता है। मुझे त्रुटि मिलती है "TypeError: Cannot read property 'FirstValue' of undefined"। मैं एक मानक संख्यात्मक एनम का उपयोग कर रहा हूं। यह एओटी के साथ ठीक काम करता है लेकिन इसके साथ नहीं --prod। यह काम करता है अगर मैं इसे HTML में पूर्णांकों का उपयोग करने के लिए बदलूं, लेकिन यह बात नहीं है। कोई विचार?
रसेल

47

यह सरल और एक आकर्षण की तरह काम करता है :) बस इस तरह से अपनी दुश्मनी की घोषणा करें और आप इसे HTML टेम्पलेट पर उपयोग कर सकते हैं

  statusEnum: typeof StatusEnum = StatusEnum;

अनुसंधान के दिनों के बाद आखिरकार मुझे वह मिल गया जिसकी मुझे आवश्यकता थी। बहुत धन्यवाद!
गृध्रसेज २४'१

@Rahul StatusEnumको .tsकक्षाओं में से एक में परिभाषित किया गया है । कोणीय घटक में आप इसे आयात करते हैं, इसे एक घटक संपत्ति (यहाँ statusEnum) से बाँधते हैं और घटक गुण टेम्पलेट से सुलभ होते हैं।
टॉम

टैंक यह महान है
परेशानी खादी

45

Angular4 - HTML टेम्पलेट ngSwitch / ngSwitchCase में Enum का उपयोग करना

यहाँ समाधान: https://stackoverflow.com/a/42464835/802196

साभार: @snorkpete

आपके घटक में, आपके पास है

enum MyEnum{
  First,
  Second
}

फिर आपके घटक में, आप सदस्य 'MyEnum' के माध्यम से Enum प्रकार में लाते हैं, और अपने enum चर 'myEnumVar' के लिए एक और सदस्य बनाते हैं:

export class MyComponent{
  MyEnum = MyEnum;
  myEnumVar:MyEnum = MyEnum.Second
  ...
}

अब आप अपने .html टेम्पलेट में myEnumVar और MyEnum का उपयोग कर सकते हैं। जैसे, ngSwitch में Enums का उपयोग करना:

<div [ngSwitch]="myEnumVar">
  <div *ngSwitchCase="MyEnum.First"><app-first-component></app-first-component></div>
  <div *ngSwitchCase="MyEnum.Second"><app-second-component></app-second-component></div>
  <div *ngSwitchDefault>MyEnumVar {{myEnumVar}} is not handled.</div>
</div>

आप एक अलग घटक में समान एनुम का पुन: उपयोग कैसे कर सकते हैं?
फॉरेस्ट

1
मुझे "निर्यात enum MyEnum {...}" का उपयोग करके बाहरी फाइल में एनम को परिभाषित करना था। फिर घटक फ़ाइल में, उस बाहरी फ़ाइल से 'MyEnum' आयात करें, और 'MyEnum = MyEnum "आदि के लिए उपरोक्त समाधान के साथ जारी रखें
ObjectiveTC

16

के रूप में rc.6 / अंतिम

...

export enum AdnetNetworkPropSelector {
    CONTENT,
    PACKAGE,
    RESOURCE
}

<div style="height: 100%">
          <div [ngSwitch]="propSelector">
                 <div *ngSwitchCase="adnetNetworkPropSelector.CONTENT">
                      <AdnetNetworkPackageContentProps [setAdnetContentModels]="adnetNetworkPackageContent.selectedAdnetContentModel">
                                    </AdnetNetworkPackageContentProps>
                  </div>
                 <div *ngSwitchCase="adnetNetworkPropSelector.PACKAGE">
                </div>
            </div>              
        </div>


export class AdnetNetwork {       
    private adnetNetworkPropSelector = AdnetNetworkPropSelector;
    private propSelector = AdnetNetworkPropSelector.CONTENT;
}

1
क्या बदल गया?
कार्ल जी।

ngSwitchCase के साथ प्रतिस्थापित
जन्म 2

आह ठीक है। धन्यवाद!
कार्ल जी।

14

@ एरिक लीज डेकोरेटर के विकल्प के रूप में, जो दुर्भाग्य से काम नहीं करता है --aot(और इस तरह)--prod ) बनाता है, मैंने एक सेवा का उपयोग करने का सहारा लिया, जो मेरे सभी एप्लिकेशन के एनमोज़ को उजागर करता है। बस एक आसान नाम के तहत, प्रत्येक घटक में इसे सार्वजनिक रूप से इंजेक्ट करने की आवश्यकता होती है, जिसके बाद आप अपने विचार में इनमों तक पहुंच सकते हैं। उदाहरण के लिए:

सर्विस

import { Injectable } from '@angular/core';
import { MyEnumType } from './app.enums';

@Injectable()
export class EnumsService {
  MyEnumType = MyEnumType;
  // ...
}

अपने मॉड्यूल की प्रदाता सूची में इसे शामिल करना न भूलें।

घटक वर्ग

export class MyComponent {
  constructor(public enums: EnumsService) {}
  @Input() public someProperty: MyEnumType;

  // ...
}

घटक HTML

<div *ngIf="someProperty === enums.MyEnumType.SomeValue">Match!</div>

मुझे सेवा को बदलने और इसे काम करने के लिए @Injectable ({प्रदान किया गया:} रूट ’}) लिखने की भी आवश्यकता थी। धन्यवाद!
स्टल्ली

2

'क्या मैं वास्तव में विचार कर रहा हूं में ऐसा करना चाहता ?'

मुझे सीधे HTML में एनमों को संदर्भित करने में कोई समस्या नहीं है, लेकिन कुछ मामलों में क्लीनर विकल्प हैं जो टाइप-सेफ-नेस नहीं खोते हैं। उदाहरण के लिए यदि आप मेरे अन्य उत्तर में दिखाए गए दृष्टिकोण को चुनते हैं, तो आपने अपने घटक में TT को कुछ इस तरह घोषित किया हो सकता है:

public TT = 
{
    // Enum defines (Horizontal | Vertical)
    FeatureBoxResponsiveLayout: FeatureBoxResponsiveLayout   
}

अपने HTML में एक अलग लेआउट दिखाने के लिए, आपके पास *ngIfप्रत्येक लेआउट प्रकार के लिए होगा, और आप अपने घटक के HTML में सीधे एनम को संदर्भित कर सकते हैं:

*ngIf="(featureBoxResponsiveService.layout | async) == TT.FeatureBoxResponsiveLayout.Horizontal"

यह उदाहरण वर्तमान लेआउट को प्राप्त करने के लिए एक सेवा का उपयोग करता है, इसे async पाइप के माध्यम से चलाता है और फिर इसकी तुलना हमारे enum मान से करता है। यह सुंदर क्रिया है, जटिल और देखने में ज्यादा मजेदार नहीं है। यह एनम के नाम को भी उजागर करता है, जो स्वयं अत्यधिक क्रिया हो सकती है।

वैकल्पिक, जो HTML से प्रकार की सुरक्षा को बरकरार रखता है

वैकल्पिक रूप से आप निम्न कार्य कर सकते हैं, और अपने घटक की .ts फ़ाइल में अधिक पठनीय फ़ंक्शन की घोषणा कर सकते हैं।

*ngIf="isResponsiveLayout('Horizontal')"

बहुत क्लीनर! लेकिन अगर कोई 'Horziontal'गलती से टाइप करे तो क्या होगा ? संपूर्ण कारण जो आप HTML में एनम का उपयोग करना चाहते थे, वह सही प्रकार से हो सकता है?

हम अभी भी कीफ और कुछ टाइपस्क्रिप्ट जादू के साथ प्राप्त कर सकते हैं । यह फ़ंक्शन की परिभाषा है:

isResponsiveLayout(value: keyof typeof FeatureBoxResponsiveLayout)
{
    return FeatureBoxResponsiveLayout[value] == this.featureBoxResponsiveService.layout.value;
}

नोट का उपयोग करें FeatureBoxResponsiveLayout[string]जो एनम के संख्यात्मक मान में पारित स्ट्रिंग मान को कनवर्ट करता है।

यदि आप अमान्य मान का उपयोग करते हैं तो यह AOT संकलन के साथ एक त्रुटि संदेश देगा।

प्रकार "" H4or क्षैतिज "का तर्क" "कार्यक्षेत्र" प्रकार के पैरामीटर के लिए उपलब्ध नहीं है "क्षैतिज"

वर्तमान में VSCode H4orizontalHTML संपादक में रेखांकित करने के लिए पर्याप्त स्मार्ट नहीं है , लेकिन आपको संकलन समय (-prod build या --aot switch) के साथ चेतावनी मिलेगी। भविष्य के अपडेट में भी इसमें सुधार किया जा सकता है।


सुनिश्चित नहीं है कि अगर मुझे अंदर स्थिरांक पसंद है, htmlलेकिन मैं आपकी बात देखता हूं और इसका उपयोग करना शुरू कर देता हूं; यह काम करता है, अच्छे पुराने दिनों के रूप में, जब संकलन! :)
जेनुअल्फा

@ जेनुमिनाफा यह दृष्टिकोण वास्तव में एनुम को html से बाहर निकालने के बारे में है, लेकिन फिर भी एनम मूल्यों को संकलित करने की अनुमति देता है। मुझे लगता है कि आप कह सकते हैं कि यह ts से html को डिकॉउंड करता है, लेकिन अपने आप में कोई वास्तविक लाभ प्रदान नहीं करता है क्योंकि वे हमेशा एक साथ उपयोग किए जाते हैं।
सिमोन_विवर

मुझे टाइप चेक पसंद है, विशेष रूप से गैर-स्वचालित रूप से परीक्षण किए गए विकास में
realfafa

"पर विचार करके प्रारंभ 'क्या मैं वास्तव में ऐसा करना चाहते हैं?'" उद्घाटन लाइन की वजह से वोट दें
WebDever

2

मेरे घटक ने एक myClassObjectप्रकार की वस्तु का उपयोग किया MyClass, जो स्वयं उपयोग कर रहा था MyEnum। यह ऊपर वर्णित एक ही मुद्दे को जन्म देता है। इसे करके हल किया:

export enum MyEnum {
    Option1,
    Option2,
    Option3
}
export class MyClass {
    myEnum: typeof MyEnum;
    myEnumField: MyEnum;
    someOtherField: string;
}

और फिर इस रूप में टेम्पलेट का उपयोग कर

<div [ngSwitch]="myClassObject.myEnumField">
  <div *ngSwitchCase="myClassObject.myEnum.Option1">
    Do something for Option1
  </div>
  <div *ngSwitchCase="myClassObject.myEnum.Option2">
    Do something for Option2
  </div>
  <div *ngSwitchCase="myClassObject.myEnum.Option3">
    Do something for Opiton3
  </div>
</div>

1

यदि 'टाइप संदर्भ' दृष्टिकोण का उपयोग कर (@ जील जी से) और आप कई प्रकार की तालिकाओं का उपयोग कर रहे हैं, तो आप इस तरह से विचार कर सकते हैं:

export default class AppComponent {

  // Store a reference to the enums (must be public for --AOT to work)
  public TT = { 
       CellType: CellType, 
       CatType: CatType, 
       DogType: DogType 
  };

  ...

  dog = DogType.GoldenRetriever; 

इसके बाद अपनी html फाइल में एक्सेस करें

{{ TT.DogType[dog] }}   => "GoldenRetriever"

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

आप एक वैश्विक भी डाल सकते हैं TT कहीं पर और आवश्यकतानुसार इसमें एनम जोड़ सकते हैं (यदि आप चाहते हैं कि यह आपको एक सेवा बना सके जैसा @VincentSels उत्तर द्वारा दिखाया गया है)। यदि आपके पास कई टाइपटेबल्स हैं तो यह बोझिल हो सकता है।

इसके अलावा, आप हमेशा एक छोटा नाम पाने के लिए अपनी घोषणा में उनका नाम बदल देते हैं।

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