2017-11-13 4 views
1

タイトルが正しく私の質問に似ているかどうかはわかりませんが、私は提案を受け付けています。インターフェイスまたは拡張インターフェイスの配列を返します

私はIListItemの配列またはそのインターフェイスを拡張する他のインターフェイスの配列のいずれかを返す次のメソッドを持っています。

export interface IListItem { 
    [key: string]: any; 
    id: string; 
    title: string; 
    modified: Date; 
    created: Date; 
    modifiedby: string; 
    createdby: string; 
} 




import {IListItem} from "./IListItem"; 

export interface INewsListItem extends IListItem { 
    newsheader: string; 
    newsbody: string; 
    expiryDate: Date; 
} 

import {IListItem} from "./IListItem"; 

export interface IAnnouncementListItem extends IListItem { 
    announcementBody: string; 
    expiryDate: Date; 
} 


import {IListItem} from "./IListItem"; 

export interface IDirectoryListItem extends IListItem { 
     firstName: string; 
     lastName: string; 
     mobileNumber: string; 
     internalNumber: string; 
} 

そしてTSXコンポーネントから消費者の方法は次のとおりです:

import { SPHttpClient, SPHttpClientResponse } from "@microsoft/sp-http"; 
import { IWebPartContext } from "@microsoft/sp-webpart-base"; 
import { IListItem} from "./models/IListItem"; 
import { IFactory } from "./IFactory"; 
import { INewsListItem } from "./models/INewsListItem"; 
import { IDirectoryListItem } from "./models/IDirectoryListItem"; 
import { IAnnouncementListItem } from "./models/IAnnouncementListItem"; 

export class ListItemFactory implements IFactory { 
    private _listItems: IListItem[]; 
    public getItems(requester: SPHttpClient, siteUrl: string, listName: string): Promise<IListItem[]> { 
     switch(listName) { 
      case "GenericList": 
       let items: IListItem[]; 
       // tslint:disable-next-line:max-line-length 
       return requester.get(`${siteUrl}/_api/web/lists/getbytitle('${listName}')/items?$select=Title,Id,Modified,Created,Author/Title,Editor/Title&$expand=Author,Editor`, 
       SPHttpClient.configurations.v1, 
       { 
        headers: { 
         "Accept": "application/json;odata=nometadata", 
         "odata-version": "" 
        } 
       }) 
       .then((response: SPHttpClientResponse): Promise<{ value: IListItem[] }> => { 
        return response.json(); 
       }) 
       .then((json: { value: IListItem[] }) => { 
        console.log(JSON.stringify(json.value)); 
        return items=json.value.map((v,i)=>(
         { 
          //key: v.id, 
          id: v.Id, 
          title: v.Title, 
          created: v.Created, 
          createdby: v.Author.Title, 
          modified: v.Modified, 
          modifiedby: v.Editor.Title       
         } 
        )); 
       }); 
      case "News": 
       let newsitems: INewsListItem[]; 
       // tslint:disable-next-line:max-line-length 
       return requester.get(`${siteUrl}/_api/web/lists/getbytitle('${listName}')/items?$select=Title,Id,Modified,Created,Created By,Modified By,newsheader,newsbody,expiryDate`, 
       SPHttpClient.configurations.v1, 
       { 
        headers: { 
         "Accept": "application/json;odata=nometadata", 
         "odata-version": "" 
        } 
       }) 
       .then((response: SPHttpClientResponse): Promise<{ value: INewsListItem[] }> => { 
        return response.json(); 
       }) 
       .then((json: { value: INewsListItem[] }) => { 
        return items=json.value.map((v,i)=>(
         { 
          id: v.Id, 
          title: v.Title, 
          created: v.Created, 
          createdby: v.Author.Title, 
          modified: v.Modified, 
          modifiedby: v.Editor.Title, 
          newsheader: v.newsheader, 
          newsbody: v.newsbody, 
          expiryDate: v.expiryDate 
         } 
        )); 
       }); 
      case "Announcements": 
       let announcementitems: IAnnouncementListItem[]; 
       return requester.get(`${siteUrl}/_api/web/lists/getbytitle('${listName}')/items?$select=Title,Id`, 
       SPHttpClient.configurations.v1, 
       { 
        headers: { 
         "Accept": "application/json;odata=nometadata", 
         "odata-version": "" 
        } 
       }) 
       .then((response: SPHttpClientResponse): Promise<{ value: IAnnouncementListItem[] }> => { 
        return response.json(); 
       }) 
       .then((json: { value: IAnnouncementListItem[] }) => { 
        return items=json.value.map((v,i)=>(
         { 
          id: v.Id, 
          title: v.Title, 
          created: v.Created, 
          createdby: v.Author.Title, 
          modified: v.Modified, 
          modifiedby: v.Editor.Title, 
          announcementBody: v.announcementBody, 
          expiryDate: v.expiryDate 
         } 
        )); 
       }); 
      case "Directory": 
       let directoryitems: IDirectoryListItem[]; 
       return requester.get(`${siteUrl}/_api/web/lists/getbytitle('${listName}')/items?$select=Title,Id`, 
       SPHttpClient.configurations.v1, 
       { 
        headers: { 
         "Accept": "application/json;odata=nometadata", 
         "odata-version": "" 
        } 
       }) 
       .then((response: SPHttpClientResponse): Promise<{ value: IDirectoryListItem[] }> => { 
        return response.json(); 
       }) 
       .then((json: { value: IDirectoryListItem[] }) => { 
        return items=json.value.map((v,i)=>(
         { 
          id: v.Id, 
          title: v.Title, 
          created: v.Created, 
          createdby: v.Author.Title, 
          modified: v.Modified, 
          modifiedby: v.Editor.Title, 
          firstName: v.firstName, 
          lastName: v.lastName, 
          mobileNumber: v.mobileNumber, 
          internalNumber: v.internalNumber 
         } 
        )); 
       }); 
      default: 
       return null; 
     } 
     } 
} 

インタフェースは、ここにいる私はちょうど参照

//#region Imports 
import * as React from "react"; 
import styles from "./FactoryMethod.module.scss"; 
import { IFactoryMethodProps } from "./IFactoryMethodProps"; 
import { 
    IDetailsListItemState, 
    IDetailsNewsListItemState, 
    IDetailsDirectoryListItemState, 
    IDetailsAnnouncementListItemState, 
    IFactoryMethodState 
} from "./IFactoryMethodState"; 
import { IListItem } from "./models/IListItem"; 
import { IAnnouncementListItem } from "./models/IAnnouncementListItem"; 
import { INewsListItem } from "./models/INewsListItem"; 
import { IDirectoryListItem } from "./models/IDirectoryListItem"; 
import { escape } from "@microsoft/sp-lodash-subset"; 
import { SPHttpClient, SPHttpClientResponse } from "@microsoft/sp-http"; 
import { ListItemFactory} from "./ListItemFactory"; 
import { TextField } from "office-ui-fabric-react/lib/TextField"; 
import { 
    DetailsList, 
    DetailsListLayoutMode, 
    Selection, 
    buildColumns, 
    IColumn 
} from "office-ui-fabric-react/lib/DetailsList"; 
import { MarqueeSelection } from "office-ui-fabric-react/lib/MarqueeSelection"; 
import { autobind } from "office-ui-fabric-react/lib/Utilities"; 
import PropTypes from "prop-types"; 
//#endregion 


export default class FactoryMethod extends React.Component<IFactoryMethodProps, IFactoryMethodState> { 
    constructor(props: IFactoryMethodProps, state: any) { 
    super(props); 
    this.setInitialState(); 
    } 

    // lifecycle help here: https://staminaloops.github.io/undefinedisnotafunction/understanding-react/ 

    //#region Mouting events lifecycle 

    // the data returned from render is neither a string nor a DOM node. 
    // it's a lightweight description of what the DOM should look like. 
    // inspects this.state and this.props and create the markup. 
    // when your data changes, the render method is called again. 
    // react diff the return value from the previous call to render with 
    // the new one, and generate a minimal set of changes to be applied to the DOM. 
    public render(): React.ReactElement<IFactoryMethodProps> { 
    switch(this.props.listName) { 
     case "GenericList": 
      // tslint:disable-next-line:max-line-length 
      return <this.ListMarqueeSelection items={this.state.DetailsListItemState.items} columns={this.state.columns} />; 
     case "News": 
      // tslint:disable-next-line:max-line-length 
      return <this.ListMarqueeSelection items={this.state.DetailsNewsListItemState.items} columns={this.state.columns}/>; 
     case "Announcements": 
      // tslint:disable-next-line:max-line-length 
      return <this.ListMarqueeSelection items={this.state.DetailsAnnouncementListItemState.items} columns={this.state.columns}/>; 
     case "Directory": 
      // tslint:disable-next-line:max-line-length 
      return <this.ListMarqueeSelection items={this.state.DetailsDirectoryListItemState.items} columns={this.state.columns}/>; 
     default: 
      return null; 
    } 
    } 

    // invoked once, only on the client (not on the server), immediately AFTER the initial rendering occurs. 
    public componentDidMount(): void { 
    // you can access any refs to your children 
    // (e.g., to access the underlying DOM representation - ReactDOM.findDOMNode). 
    // the componentDidMount() method of child components is invoked before that of parent components. 
    // if you want to integrate with other JavaScript frameworks, 
    // set timers using setTimeout or setInterval, 
    // or send AJAX requests, perform those operations in this method. 
    this._configureWebPart = this._configureWebPart.bind(this); 
    this.readItemsAndSetStatus(); 
    } 

    //#endregion 

    //#region Props changes lifecycle events (after a property changes from parent component) 
    public componentWillReceiveProps(nextProps: IFactoryMethodProps): void { 
    if(nextProps.listName !== this.props.listName) { 
     this.readItemsAndSetStatus(); 
    } 
    } 

    //#endregion 

    //#region private methods 
    private _configureWebPart(): void { 
    this.props.configureStartCallback(); 
    } 

    public setInitialState(): void { 
    this.state = { 
     type: "ListItem", 
     status: this.listNotConfigured(this.props) 
     ? "Please configure list in Web Part properties" 
     : "Ready", 
     columns:[], 
     DetailsListItemState:{ 
     items:[] 
     }, 
     DetailsNewsListItemState:{ 
     items:[] 
     }, 
     DetailsDirectoryListItemState:{ 
     items:[] 
     }, 
     DetailsAnnouncementListItemState:{ 
     items:[] 
     }, 
    }; 
    } 

    // reusable inline component 
    private ListMarqueeSelection = (itemState: {columns: IColumn[], items: IListItem[] }) => (
     <div> 
      <DetailsList 
      items={ itemState.items } 
      columns={ itemState.columns } 
      setKey="set" 
      layoutMode={ DetailsListLayoutMode.fixedColumns } 
      selectionPreservedOnEmptyClick={ true } 
      compact={ true }> 
      </DetailsList> 
     </div> 
) 

    // read items using factory method pattern and sets state accordingly 
    private readItemsAndSetStatus(): void { 
    this.setState({ 
     status: "Loading all items..." 
    }); 

    const factory: ListItemFactory = new ListItemFactory(); 
    factory.getItems(this.props.spHttpClient, this.props.siteUrl, this.props.listName) 
    .then((items: IListItem[]) => { 
     const keyPart: string = this.props.listName === "GenericList" ? "" : this.props.listName; 
     // the explicit specification of the type argument `keyof {}` is bad and 
     // it should not be required. 
     this.setState<keyof {}>({ 
      status: `Successfully loaded ${items.length} items`, 
      ["Details" + keyPart + "ListItemState"] : { 
      items 
      }, 
      columns: buildColumns(items) 
     }); 
    }); 
    } 

    private listNotConfigured(props: IFactoryMethodProps): boolean { 
    return props.listName === undefined || 
     props.listName === null || 
     props.listName.length === 0; 
    } 

    //#endregion 
} 
のために全体TSXの下に貼り付ける

// read items using factory method pattern and sets state accordingly 
    private readItemsAndSetStatus(): void { 
    this.setState({ 
     status: "Loading all items..." 
    }); 

    const factory: ListItemFactory = new ListItemFactory(); 
    factory.getItems(this.props.spHttpClient, this.props.siteUrl, this.props.listName) 
    .then((items: IListItem[]) => { 
     const keyPart: string = this.props.listName === "GenericList" ? "" : this.props.listName; 
     // the explicit specification of the type argument `keyof {}` is bad and 
     // it should not be required. 
     this.setState<keyof {}>({ 
      status: `Successfully loaded ${items.length} items`, 
      ["Details" + keyPart + "ListItemState"] : { 
      items 
      }, 
      columns: buildColumns(items) 
     }); 
    }); 
    } 

問題は、そのリストアイテムの常にreturninアレイ、従ってザが反応コンポーネントのみIListItemの列を表示するが、他のインターフェイス

アップデート1の列に表示されない:その後にキャストを実行しようと

は、になりますが変数myItemsの重複した警告。

enter image description here

+0

あなたは 'buildColumn'のコードを投稿することができmyItemsを使うのか? – palsrealm

+0

私はそのメソッドを開発しなかった、それはこのコンポーネントから来ています。 https://developer.microsoft.com/en-us/fabric#/components/detailslist –

答えて

1

あなたの約束がIListItem []を返しているので、それは問題です。

ファクトリのgetItemsメソッドの約束の戻り値の型を[]に変更した場合。その後、消費者のgetItemsメソッド呼び出しの 'then'の戻り値の型に同じ処理を行います。次に、消費者のリスト名の別のスイッチを使用して、必要なタイプにキャストします。

castこれはコンシューマーで使用できるリスト名があるためです。

var myItems = null; switch(listName) { case "GenericList": myItems = items as IListItem[]; case "News": myItems = items as INewsListItem[]; case "Announcements": myItems = items as IAnnouncementListItem[]; case "Directory": myItems = items as IDirectoryListItem[]; }

とあなたの代わりにアイテムの列を構築するときに

+0

どのようにして消費者にキャスティングを行うことができますか? –

+0

オリジナルの投稿を更新しました。うまくいきたいです! –

+0

私はあなたの考えを理解していますが、誤解しているかもしれません。スクリーンショットで私のアップデート1をご覧ください。 –

関連する問題