1

I am currently building an RSS webpart in SPFx using React as a framework.

Now I am in the stage that I want the user to be able to select how many news items he/she want to see with a slider (taken from UI Fabrics). I have a settings button which takes me to a side panel (UI Fabrics) containing the slider.

The problem is that when I choose a value with the slider and click Save, it shows the chosen value in the console but all content disappears in the webpart.

I'll provide screenshots and code here to illustrate what I mean:

The app in the beginning showing 3 news items since I set its state to show 3 initially: enter image description here

The side drawer appears when I click "Settings" button, containing the slider: enter image description here

Let say I set the slider to 9 and Save:

enter image description here

After applying save button, all content in the app vanish but the right value appears in the console (which is the number I wish to set how many items to be shown in the webpart): enter image description here

Here is the problem, I want the value now shown in Console to be the value which decides how many news items to render in the webpart.

Here I will show code: RssApp.tsx (Function for saving value in _saveSettings. I send value from slider to _saveSettings.):

import * as React from 'react';
import styles from '../RssApp.module.scss';
import { IRssAppProps } from './IRssAppProps';
import {IRssItem} from './IRssAppState'

import { PrimaryButton } from 'office-ui-fabric-react';
import { DefaultButton } from 'office-ui-fabric-react/lib/Button';
import { Panel, PanelType } from 'office-ui-fabric-react/lib/Panel';
import { Slider } from 'office-ui-fabric-react/lib/Slider';


export default class RssApp extends React.Component<IRssAppProps, any> {
  constructor(props: IRssAppProps){
    super(props);
    this.state = {
        items: [],    
        title: '',
        description: '',
        author: '',
        showPanel: false,
        numberOfNewsItems: 3
    };

  }

  public showSomeXML(){

      var xhttp = new XMLHttpRequest();

      xhttp.onreadystatechange = () => {

        if(xhttp.readyState == 4 && xhttp.status == 200){

          let newsFeedElementsArray: IRssItem[] = []; //an array to push
          let allItems = xhttp.responseXML.getElementsByTagName('item').length;
          /**For loop iterating over items (i.e. all news article items) */
          for(let i = 0; i < this.state.numberOfNewsItems; i++){

             let heading = xhttp.responseXML.getElementsByTagName('item')[i].children[3].innerHTML; //title
             let intro = xhttp.responseXML.getElementsByTagName('item')[i]
                              .children[4].innerHTML
                              .replace("<![CDATA[", "")
                              .replace("]]", "").replace(/<[^>]*>/g, '');
             let author = xhttp.responseXML.getElementsByTagName('item')[i].children[2].innerHTML;
            /***Showing in the console */
             console.log("Title: " + heading);
             console.log("Description: " + xhttp.responseXML.getElementsByTagName('item')[i]
                          .children[4].innerHTML.replace("<![CDATA[", "").replace("]]", ""));
             console.log("Author: " + xhttp.responseXML.getElementsByTagName('item')[i].children[2].innerHTML);   

              //Push all content to array and set them to state
            newsFeedElementsArray.push({
                  title: heading,
                  description: intro,
                  author: author,
                  showPanel: false,
                  numberOfNewsItems: 6
            });

          }  
             /**Set State to innerHTML from the xml file */
                this.setState(
                {  
                  items: newsFeedElementsArray //Newly added
                });
                console.log("News items: " + xhttp.responseXML.getElementsByTagName('item').length);
                console.log(xhttp.responseXML.getElementsByTagName('item')[1].children);
        }
      };
      xhttp.open("GET", 'https://feeds.expressen.se/nyheter/', true);
      xhttp.send();
  }

    //**Save settings for RSS Feed */
    private _saveSettings = (value, heading, intro, author) => {
      let newsFeedElementsArray: IRssItem[] = []; //an array to push
        this.setState({
            title: heading,
            description: intro,
            author: author,
            numberOfNewsItems: value,
            showPanel: false
        });
        for(let i = 0; i < value; i++){
            newsFeedElementsArray.push({
                title: heading,
                description: intro,
                author: author,
                showPanel: false,
                numberOfNewsItems: value
            });
        }
        this.setState({
          items: newsFeedElementsArray
        })
        console.log("News items to display: " + this.state.numberOfNewsItems); 
    }


  public render(): React.ReactElement<IRssAppProps> {
    let newsElement = (element: IRssItem)=> { //Newly added
        return (
              <div className={ styles.row }>
                  <div className={styles.title}>{element.title}</div>
                  <div className={ styles.description }>{element.description}</div>
                  <div>{element.author}</div>
              </div>
        );
    };//Newly added

    //**Settings side panel  */
    let settingsPanel = (
      <div>
        <Panel
          isOpen={this.state.showPanel}
          type={PanelType.smallFixedFar}
          onDismiss={this._hidePanel}
          isFooterAtBottom={true}
          headerText="RSS Feed Settings"
          closeButtonAriaLabel="Close"
          onRenderFooterContent={this._onRenderFooterContent}
        >
        {/* Slider to adjust how many news the user want to display in the feed */}
        <Slider
          label="How many news do you want to display?"
          min={1}
          max={20}
          step={1}
          value={this.state.numberOfNewsItems}
          showValue={true}
          onChange={value => { 
            this.setState({numberOfNewsItems: value})

           }
          }
        />
          <span>{"News items to display: " + this.state.numberOfNewsItems}</span>
        </Panel>
      </div>  
  );

    return (
      <div className = {styles.column}>

          <DefaultButton
            data-automation-id="test"
            text="Settings"
            onClick={this._showPanel}
          /> 
          {this.state.items.map(newsElement)}
          {settingsPanel}
      </div>


    );
  }

//**Save and Cancel buttons in the side panel */
  _onRenderFooterContent = (value) => {
    return (
      <div>
        <PrimaryButton onClick={() => this._saveSettings(value, this.state.title, this.state.title, this.state.author)} style={{ marginRight: '8px' }}>
          Save
        </PrimaryButton>
        <DefaultButton onClick={this._hidePanel}>Cancel</DefaultButton>
      </div>
    );
  };

    componentDidMount(){
    {this.showSomeXML()}
  }

  private _showPanel = () => {
    this.setState({ showPanel: true });
  };

  private _hidePanel = () => {
    this.setState({ showPanel: false });
  };
}

IRssAppState.ts:

export interface IRssItem{
    title: string;
    description: string;
    author: string;
    showPanel: boolean;
    numberOfNewsItems: number;
}

//export interface 

export interface IRssAppState{ 
    items: IRssItem[];
}

All help and advice is appreciated. Thanks in advance!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.