Преобразовать SPFX TS без JS фреймворка в React TS - PullRequest
1 голос
/ 26 января 2020

Я использовал yo @ microsoft / sharepoint, чтобы создать веб-часть для отображения списка элементов. Решение было создано без Javascript framework.

import { Version } from '@microsoft/sp-core-library';
import { BaseClientSideWebPart } from '@microsoft/sp-webpart-base';
import {
  IPropertyPaneConfiguration,
  PropertyPaneTextField
} from '@microsoft/sp-property-pane';
import { escape } from '@microsoft/sp-lodash-subset';

import styles from './GetSpListItemsWebPart.module.scss';
import * as strings from 'GetSpListItemsWebPartStrings';

import {
  SPHttpClient,
  SPHttpClientResponse   
} from '@microsoft/sp-http';
import {
  Environment,
  EnvironmentType
} from '@microsoft/sp-core-library';

export interface IGetSpListItemsWebPartProps {
  description: string;
}
export interface ISPLists {
  value: ISPList[];
}

export interface ISPList {
  ID:string;
  Title: string;
  Summary : string;
  NewsCategory: string;
  Created:string;


    AttachmentFiles:{
      Name:string;
      Url:string;
    ServerRelativeUrl: string;
    }



}

export default class GetSpListItemsWebPart extends BaseClientSideWebPart<IGetSpListItemsWebPartProps> {
  private _getListData(): Promise<ISPLists> {
    return this.context.spHttpClient.get(this.context.pageContext.web.absoluteUrl + "/_api/lists/GetByTitle('News')/items?$select=*&$expand=AttachmentFiles",SPHttpClient.configurations.v1)
        .then((response: SPHttpClientResponse) => {
        return response.json();
        });
    }
    private _renderListAsync(): void {

      if (Environment.type == EnvironmentType.SharePoint || 
               Environment.type == EnvironmentType.ClassicSharePoint) {
       this._getListData()
         .then((response) => {
           this._renderList(response.value);
         });
     }
   }



      public titleurl(query:string){
        var path="/Lists/News/DispForm.aspx?ID=";
        var currdir=this.context.pageContext.web.absoluteUrl;
       var result=currdir+path+query;


        return result;

      }

    private _renderList(items: ISPList[]): void {
      let html: string = '<table border=1 width=100% style="border-collapse: collapse;">';
      html += '<th>ID</th><th>Title</th> <th>Summary</th><th>Created</th><th>Attachments</th>';
      items.forEach((item: ISPList) => {
        html += `
        <tr>     
        <td>${item.ID}</td>       
            <td><a href="${this.titleurl(item.ID)}">${item.Title}</a></td>
            <td>${item.Title}</td>
            <td>${item.Created}</td>
            <td>
            <img src="${item.AttachmentFiles[0].ServerRelativeUrl}" width="300px" height="300px" />
            </td>

            </tr>
            `;
      });
      html += '</table>';

      const listContainer: Element = this.domElement.querySelector('#spListContainer');
      listContainer.innerHTML = html;
    }

  public render(): void {
    this.domElement.innerHTML = `
      <div class="${ styles.getSpListItems }">
        <div class="${ styles.container }">
          <div class="ms-Grid-row ms-bgColor-themeDark ms-fontColor-white ${ styles.row }">
          <div class="ms-Grid-col ms-u-lg10 ms-u-xl8 ms-u-xlPush2 ms-u-lgPush1">
          <span class="ms-font-xl ms-fontColor-white">Welcome to SharePoint Modern Developmennt</span>
          <p class="ms-font-l ms-fontColor-white">Loading from ${this.context.pageContext.web.title}</p>
          <p class="ms-font-l ms-fontColor-white">Retrive Data from SharePoint List</p>
        </div>
      </div> 
          <div class="ms-Grid-row ms-bgColor-themeDark ms-fontColor-white ${styles.row}">
          <div>NEWS List Items</div>
          <br>
           <div id="spListContainer" />
        </div>
      </div>`;
      this._renderListAsync();
  }

  protected get dataVersion(): Version {
    return Version.parse('1.0');
  }

  protected getPropertyPaneConfiguration(): IPropertyPaneConfiguration {
    return {
      pages: [
        {
          header: {
            description: strings.PropertyPaneDescription
          },
          groups: [
            {
              groupName: strings.BasicGroupName,
              groupFields: [
                PropertyPaneTextField('description', {
                  label: strings.DescriptionFieldLabel
                })
              ]
            }
          ]
        }
      ]
    };
  }
}

Эта часть была успешно обработана.

Затем я создал решение yo @ microsoft / sharepoint, используя React вариант. Я застрял на том, как сделать документы HTML. Предыдущий это, как привыкли к this.domElement, но он говорит, что это не в классе. Я пытался создать другой класс для рендеринга, кажется, неудачно. Как распечатать результаты?

import * as React from 'react';
import styles from './B.module.scss';
import { IBProps } from './IBProps';
import { escape } from '@microsoft/sp-lodash-subset';

import {
  SPHttpClient,
  SPHttpClientResponse   
} from '@microsoft/sp-http';
import {
  Environment,
  EnvironmentType
} from '@microsoft/sp-core-library';
import * as ReactDOM from 'react-dom';
export interface ISPLists {
  value: ISPList[];
}

export interface ISPList {
  ID:string;
  Title: string;
  Summary : string;
  NewsCategory: string;
  Created:string;


    AttachmentFiles:{
      Name:string;
      Url:string;
    ServerRelativeUrl: string;
    }



}



export default class B extends React.Component<IBProps, {}> {



  public render(): React.ReactElement<IBProps> {



    return (

      <div  className={ styles.b }>      
        <div id="spListContainer"></div>
        <div className={ styles.container }>
          <div className={ styles.row }>
            <div className={ styles.column }>
              <span className={ styles.title }>Welcome to SharePoint!</span>
              <p className={ styles.subTitle }>Customize SharePoint experiences using Web Parts.</p>
              <p className={ styles.description }>{escape(this.props.description)}</p>

            </div>
          </div>
        </div>
      </div>
    );
  }
}

export class shownews extends B{
  constructor(prop){
          super(prop); 

          public _getListData(): Promise<ISPLists> {
            return this.context.spHttpClient.get(this.context.pageContext.web.absoluteUrl + "/_api/lists/GetByTitle('News')/items?$select=*&$expand=AttachmentFiles",SPHttpClient.configurations.v1)
                .then((response: SPHttpClientResponse) => {
                return response.json();
                });
            }
            public _renderListAsync(): void {

              if (Environment.type == EnvironmentType.SharePoint || 
                       Environment.type == EnvironmentType.ClassicSharePoint) {
               this._getListData()
                 .then((response) => {
                   this._renderList(response.value);
                 });
             }
           }



              public titleurl(query:string){
                var path="/Lists/News/DispForm.aspx?ID=";
                var currdir=this.context.pageContext.web.absoluteUrl;
               var result=currdir+path+query;


                return result;

              }

            private _renderList(items: ISPList[]): void {

              let html: string = '<table border=1 width=100% style="border-collapse: collapse;">';
              html += '<th>ID</th><th>Title</th> <th>Summary</th><th>Created</th><th>Attachments</th>';
              items.forEach((item: ISPList) => {
                html += `
                <tr>     
                <td>${item.ID}</td>       
                    <td><a href="${this.titleurl(item.ID)}">${item.Title}</a></td>
                    <td>${item.Title}</td>
                    <td>${item.Created}</td>
                    <td>
                    <img src="${item.AttachmentFiles[0].ServerRelativeUrl}" width="300px" height="300px" />
                    </td>

                    </tr>
                    `;
              });
              html += '</table>';


              const listContainer = React.createElement('h1',{},html);
              ReactDOM.render(listContainer, document.getElementById('spListContainer'));
               this._renderListAsync();

            }

  }

}

Я приношу свои извинения Если есть много руководств по SPFX, REACT JS по операциям CRUD. Однако, я клонировал его, попытался установить npm или npm i -g, ни одно из хранилищ не работает для меня.

2020-01-28

  • Переписал код, чтобы получить json напрямую. Теги html не будут отображаться
import * as React from 'react';
import styles from './A.module.scss';
import { IAProps } from './IAProps';
import { escape } from '@microsoft/sp-lodash-subset';
import { PageContext } from "@microsoft/sp-page-context";
import { HttpClient, IHttpClientOptions, HttpClientResponse, SPHttpClient, ISPHttpClientOptions, SPHttpClientResponse } from '@microsoft/sp-http';

import {
  Environment,
  EnvironmentType
} from '@microsoft/sp-core-library';


export interface ISPLists {
  value: ISPList[];
};

export interface ISPList {
  ID:string;
  Title: string;
  Summary : string;
  NewsCategory: string;
  Created:string;
    AttachmentFiles:{
      Name:string;
      Url:string;
    ServerRelativeUrl: string;
    };

}


export default class A extends React.Component<IAProps, {}> {


  public test:any=[];
  public data:any=[];

  public geturl(query:string){
    var path="/Lists/News/DispForm.aspx?ID=";
    var currdir=this.props.pagecontext.web.absoluteUrl;
   var result=currdir+path+query;

    return result;

  }
  private getListData(){
    const opt: ISPHttpClientOptions = { headers: { 'Content-Type': 'application/json;odata=verbose' } };

    return this.props.SPHttpClient.get(this.props.pagecontext.web.absoluteUrl + "/_api/lists/GetByTitle('News')/items?$select=*&$expand=AttachmentFiles",SPHttpClient.configurations.v1,opt)
        .then((response: SPHttpClientResponse) => {
          response.json().then((json: any) => {


            for(let i=0;i<json.value.length;i++){
              this.data.push(<div><tr>
            <td>${json.ID}</td>
            <td><a href="${this.geturl(json.ID)}">${json.Title}</a></td>
            <td></td>
            <td>${json.Created}</td>
            <td><img src="${json.AttachmentFiles.ServerRelativeUrl}" width="300px" height="300px" /></td>
            </tr></div>);

              }
            });
          });
    }








     /*
  private renderList(item: ISPList[]): void {
         item.forEach((item: ISPList) => {
                       this.data.push(`<tr>
            <td>${item.ID}</td>
            <td><a href="${this.geturl(item.ID)}">${item.Title}</a></td>
            <td></td>
            <td>${item.Created}</td>
            <td><img src="${item.AttachmentFiles.ServerRelativeUrl}" width="300px" height="300px" /></td>
            </tr>`
                       );


                           })
                           console.log(this.data);


    };

    */
/*
    private push() {
      this.test.push(1);
      this.test.push(2);
      this.test.push(3);
      console.log(this.test);
    }
    */






  public render(): React.ReactElement<IAProps>{
    this.getListData();
    console.log(this.data);


     return (


      <div id="splist">


              TEST
        <table className={styles.container}>

          <tr>
        <th>ID</th><th>Title</th> <th>Summary</th><th>Created</th><th>Attachments</th>
        </tr>
        <tr>     
    <td></td>       
            <td><a href="${this.titleurl(item.ID)}">TITLE</a></td>
            <td></td>
            <td>Created</td>
            <td>
                 </td>

            </tr>

       {this.data} 

1234
        </table>
         </div>
    );
  }
}

2020-01-28 18: 15

  • Это не работает , Если я .pu sh (данные); Таблица будет иметь); повсюду.
this.setState({ items:"<td>{item.ID}</td> 
<td>{item.Title}</td> 
<td>{item.Summary}</td> 
<td>{item.Created}</td> 
<td>{item.AttachmentFiles[0].ServerRelativeUrl}</td>" });

Это не работает

this.Title.push(<span><td>{item.Title}</td></span>); 
this.Url.push(<span><td>{item.AttachmentFiles[0].ServerRelativeUrl}</td></span>); 

Это работает

this.ID.push(item.ID); /* this.Title.push(<span><td>{item.Title}</td></span>); this.Url.push(<span><td>{item.AttachmentFiles[0].ServerRelativeUrl}</td></span>); */ this.forceUpdate(); 

Если я использую массив и использую .pu sh для отправки данных, включающих теги HTML, следующий скриншот показывает проблему. image{item.ID});">

Код

 public renderList(item: ISPList[]): void {

          item.forEach((item: ISPList) => {

          this.data.push(<tr>);
          this.data.push(<td>{item.ID}</td>);
          this.data.push(<td>{item.Title}</td>);
          this.data.push(<td>{item.AttachmentFiles[0].ServerRelativeUrl}</td>);
          this.data.push(</tr>);
//some brackets...

2020-01-28 1956 Задача TR WITHIN TR Tr within a DIV Проблема: если я напишу теги HTML и данные в одну строку, теги будут генерироваться самостоятельно. Но в методе рендеринга мне нужно добавить тег для переноса, это сделает мой вывод неправильным форматом.

//some codes before to get the JSON data
 this.data.push(<tr>
            <td>{item.ID}</td>
            <td>{item.Title}</td>
            <td>{item.AttachmentFiles[0].ServerRelativeUrl}</td></tr>);
//some more codes

public render(): React.ReactElement<IAProps>{


     return (

      <div id="splist">

              TEST
        <table className={styles.container}>

          <tr>
            <th>ID</th>
            <th>Title</th>
          <th>Attachments</th>
          </tr>

         {this.data}

         </table>      
         </div>
    );
  }

Ответы [ 2 ]

1 голос
/ 27 января 2020

Во-первых, вам нужно подумать о своем решении с точки зрения компонентов (имеющих реквизиты или состояния), которые вы хотите визуализировать. В контексте вашего решения вы можете создать компонент, скажем: «GetandRenderListItems.tsx» и делать все «_getListData ()». Вы можете использовать хук жизненного цикла componentDidMount () для вызова функции _getListData () каждый раз после монтирования компонента. Затем вам нужно написать html шаблон для рендеринга полученных данных (все, что вы сделали в методе _renderList ()), взгляните на фрагмент ниже, чтобы получить представление:

     public render(): React.ReactElement<IyourcomponentsProps> {
    return (
     // your dynamic table html and you should not use inline style but define styles in 
       scss file and use them.
    );
  }

Затем в вашем В файле 'yourwebpart.ts' вы можете отобразить этот компонент в методе render ():

     public render(): void {
    const element: React.ReactElement<IyourwebpartProps > = React.createElement(
      GetandRenderListItems,
      {
        description: this.properties.description,
       // similarly assign values to  other props
      }
    );

    ReactDom.render(element, this.domElement);
  }

Надеюсь, это поможет.

Редактировать

Вы можете использовать array.map () Например, для рендеринга таблицы с использованием вашего массива вы можете написать что-то подобное.

    public render () : React.ReactElement<IyourcomponentsProps> {
    return(
        <div className={styles.someStyle} >   
          <table className={styles.container}>
           <tr>
             <th>ID</th><th>Title</th> <th>Summary</th><th>Created</th 
             <th>Attachments</th>
           </tr>

               { yourArray.map(function(item,key){    
                  let url = this.titleurl(item.ID);
                return (<tr className={styles.rowStyle} key={key}>    //you can use key if you want to track index
         <td></td>           <td className={styles.someclass}><a href={url}>{item.Title}</a></td>    

                  </tr> ); 
              })}    

          </table>    
        </div>    


    );
}
0 голосов
/ 28 января 2020

Я использовал функции .bind .map, чтобы это произошло. Для добавления состояния в проект необходимо следующее обновление. Я боролся с обработкой массивов и проблемами печати

Весь файл .tsx компонента

import * as React from 'react';
import styles from './A.module.scss';
import { IAProps } from './IAProps';
import { escape } from '@microsoft/sp-lodash-subset';
import { PageContext } from "@microsoft/sp-page-context";
import { HttpClient, IHttpClientOptions, HttpClientResponse, SPHttpClient, ISPHttpClientOptions, SPHttpClientResponse } from '@microsoft/sp-http';
import {
  Environment,
  EnvironmentType
} from '@microsoft/sp-core-library';

export interface ISPLists {
  value: ISPList[];
};

export interface Istate {
  ID:string;
  Title: string;
  isLoad?: boolean;
  Url:string;
    AttachmentFiles:{
      Name:string;
      Url:string;
    ServerRelativeUrl: string;

    };
}


export interface ISPList {
  ID:string;
  Title: string;
  Summary : string;
  NewsCategory: string;
  Created:string;
    AttachmentFiles:{
      Name:string,
      Url:string,
    ServerRelativeUrl: string,
    };

}





/*
MAIN STARTS HERE
 2020-01-28
*/ 
export default class A extends React.Component<IAProps> {

constructor(props){
  super(props);

   this.loadNews();
   this.getListData=this.getListData.bind(this);
   this.geturl=this.geturl.bind(this);
   this.loadNews=this.loadNews.bind(this);
}



//variables to render html tags
private ID:any = [];
private Title:any = [];
private Url:any = [];
private data:any =[];
private tro:any=[]; //<tr>
private trc:any=[]; //</tr>
private tdo:any=[]; //<td>
private tdc:any=[]; //</td>




private loadNews(){
  this.getListData();
  /*
  this.getListData().then((response) => {
    this.renderList(response.value);

  });
  */ // when getlist and redner list are different functions
}



  public geturl(query:string){
    var path="/Lists/News/DispForm.aspx?ID=";
    var currdir=this.props.pagecontext.web.absoluteUrl;
   var result=currdir+path+query;
       return result;
   }

private tags(flag:boolean,first:boolean){
  // if first data add <tr>
  //if last data add </tr>
  //
  if (flag && first){
    document.getElementById("tro").innerHTML = <tr>;
  }else if (flag && !first){
   document.getElementById("trc").innerHTML = </tr>;
  }

}


   private  getListData() {
    const opt: ISPHttpClientOptions = { headers: { 'Content-Type': 'application/json;odata=verbose' } };
    this.props.SPHttpClient.get(this.props.pagecontext.web.absoluteUrl + "/_api/web/lists/getbytitle('News')/items?$select=*,AttachmentFiles&$expand=AttachmentFiles/Title&$orderby=ID desc", SPHttpClient.configurations.v1, opt).then((response: SPHttpClientResponse) => {
      response.json().then((json: any) => {
         for(let i=0;i<json.value.length;i++){
          var url=this.geturl(json.value[i].ID);
            if(i==0){ // add tags <tr> </tr>
              let flag=true; let first=true;
              this.tags(flag,first);


            }else if(i==json.value.length){
              let flag=false; let first=false;
              this.tags(flag,first);

            }
            this.data.push({ID:<td>{json.value[i].ID}</td>,
             Title:<td><a href={url} target="_blank">{json.value[i].Title}</a></td>,
             Url:<td><img src={json.value[i].AttachmentFiles[0].ServerRelativeUrl} width="300px" height="300px" /></td>
              });
             //   debugger;
                              this.ID.push(json.value[i].ID);

                             // this.Title.push(json.value[i].Title);
                              //this.Url.push(json.value[i].AttachmentFiles[0].absoluteUrl);
               this.forceUpdate(); 
              }//close for
        });// close response.json  
      });//close private getListData method

    }


              // json.value[i].Title}
       //json.value[i].AttachmentFiles[0].absoluteUrl}

       /*
      <td><a href="${this.geturl(json.ID)}">${json.value[i].Title}</a></td>
        <td></td>
        <td>${json.value[i].Created}</td>
        <td><img src="${json.AttachmentFiles.ServerRelativeUrl}" width="300px" height="300px" /></td>
         */











  public render(): React.ReactElement<IAProps>{
    console.log(this.data);
       return (
    <div className={styles.a} >
             <div className={styles.container} ></div>

         <span className={ styles.title }>News</span>
         <div className={styles.Table}>  
          <div className={styles.Heading}>  
         <table >
           <tr>  
              <div className={styles.Cell}>Title</div>  
              <div className={styles.Cell}>Created</div>  
              <div className={styles.Cell}>IMGSRC</div> 
           </tr>


            <div className={styles.Cell}>
              <span id="tro"></span>
            {this.data.map((data)=>
             <div> {data.ID}</div>
            )
            }
          </div>
          <div className={styles.Cell}>
            {this.data.map((data)=>
             <div> {data.Title}</div>
                      )
            }
          </div>
          <div className={styles.Cell}>
            {this.data.map((data)=>
             <div> {data.Url}</div>
            )
            }
              <span id="trc"></span>
          </div>








            </table>
                     </div>

                  </div>
                        </div>


    );
  }
}


В методе рендеринга .map функция следующим образом

 <div className={styles.Cell}>
            {this.data.map((data)=>
             <div> {data.Url}</div>
            )
            }
              <span id="trc"></span>
          </div>

Для доступа к объектам данных в массиве необходимо объявить .bind в конструкторе после определения класса.

export default class A extends React.Component<IAProps> {

constructor(props){
  super(props);

   this.loadNews();
   this.getListData=this.getListData.bind(this);
   this.geturl=this.geturl.bind(this);
   this.loadNews=this.loadNews.bind(this);
}



//variables to render html tags

private data:any =[];

Prototype, Halfway through the project. На полпути. Это прототип. Как только я смогу извлечь данные, я смогу оформить CSS

Спасибо за вашу помощь.

...