Link to home
Start Free TrialLog in
Avatar of coder
coderFlag for Australia

asked on

to change ui onChange event of dynamically created input boxes in react redux application

Hi There,

I have 3 dynamically constructed Textboxes (input) (Location, keyword, Contributor) on a reactjs application.   I want to filter the below list of checkboxes onChange event of input boxes (Text box).  It is a react redux application.  Please see the embedded image to have a complete idea about UI.   Please suggest how to achieve this result.

User generated image
Please see the below code which I had done to create this gui on reactjs.

export default class SearchOptions extends Component {
  constructor(props) {
     super(props);
     //this.updateFacet = this.updateFacet.bind(this);
     this.onInputBoxChange = this.onInputBoxChange.bind(this);
  }

  /*updateFacet(key,value,isChecked) {
      console.log("updateFacet - " + isChecked);
      this.props.actions.updateFacet(key,value,isChecked,false);
  }*/

  onInputBoxChange(e,items,key) {
     items.map(i => console.log(i.value + " count (" + i.count + ")" ));
     console.log("target - " + e.target.value);
     var keysList = items.filter(i => i.value.toLowerCase().indexOf(e.target.value.toLowerCase().toString()) >= 0 ? true : false);
     console.log(keysList);
  }

  createListKeyValues() {
        const listKeyValues = (
          <div style={{marginLeft:10}}>
          {(()=>{
               return i.items.slice(0,3).map((j) => {

                  const label = j.value.charAt(0).toUpperCase() + j.value.slice(1);
                  const count = j.count && j.count > 0 ? ` (${j.count})` : '';
                        return (<label className="full-checkbox"> { `${label}${count}`}
                              <input type="checkbox" value={j.value}  checked={j.selected} key={j.value}
                                   onClick = {(e) => this.props.actions.updateFacet(i.key,j.value,e.target.checked,false)} />
                                   <span className="checkmark"></span>
                                  </label>)
                      });
          })()}
          </div>
       );

       return listKeyValues;
  }


  render() {
    
    const facet_list2 = this.props.facets.filter(i => i.items.length > 0).map((i) => {
        let inputName =  createSwitchKeySearchBox(i.key);

        //const inputBox = (<input type="text" name={inputName} placeholder={inputName} style={{marginBottom:10}} onChange={(e)=>this.onInputBoxChange(e,i.items)}/>);

        const inputBox = (<div class="inner-addon left-addon">
                             <i class="glyphicon gluphicon-search form-control-search"></i>
                             <input type="text" name={inputName} placeholder={inputName} style={{marginBottom:10}} onChange=
                                 {(e) => this.onInputBoxChange(e,i.items,i.key)} class="form-control" />
                          </div>);

        const keyText = (i.key === "subject")? "keyword":i.key;
        const byKeyText = (<span> By {keyText} </span>);

        const keySearchBox = (
               <div>
                   <div style={{textTransform: "capitalize", marginBottom: 8, display: "inline-block"}}>
                        {byKeyText}
                   </div>
                   {(inputName !== "Default") ? inputBox:null}
               </div>

        );

        const listKeyValues = (
          <div style={{marginLeft:10}}>
          {(()=>{
               return i.items.slice(0,3).map((j) => {

                  const label = j.value.charAt(0).toUpperCase() + j.value.slice(1);
                  const count = j.count && j.count > 0 ? ` (${j.count})` : '';
                        return (<label className="full-checkbox"> { `${label}${count}`}
                              <input type="checkbox" value={j.value}  checked={j.selected} key={j.value}
                                   onClick = {(e) => this.props.actions.updateFacet(i.key,j.value,e.target.checked,false)} />
                                   <span className="checkmark"></span>
                                  </label>)
                      });
          })()}
          </div>
        );

        return (
          <div key={i.key} style={{marginTop: 15}}>
             {keySearchBox}
             {listKeyValues}
             <a href="#" style={{marginLeft: 10, marginTop: 5,fontSize:"14px",fontWeight:"bold",color:'#C25518'}} onClick={() =>
                     this.props.actions.showAdvancedFacets(i.key)}>
                     {i.key === "date" ? "Specify date" : "MORE"}
             </a>
          </div>);
        });

    return (
      <div className="left-sidebar">
        <div className="title">Refine my results</div>
        <div className="facets">
          <div>
            <div className="drop_down_label">Thumbnails</div>
            <DropDownMenu value={this.props.thumbnailSize} onChange={(e, i, size) => this.props.actions.changeThumbnailSize(size)} style={{verticalAlign: "bottom"}}>
              <MenuItem value={0} label="Descriptive" primaryText="Descriptive" />
              <MenuItem value={.5} label="Small" primaryText="Small" />
              <MenuItem value={.75} label="Medium" primaryText="Medium" />
              <MenuItem value={1} label="Large" primaryText="Large" />
            </DropDownMenu>
          </div>

          <div>
            <div className="drop_down_label">Sort by</div>
            <DropDownMenu value={this.props.sortOrder} onChange={(e, i, sort) => this.props.actions.updateSort(sort)} style={{verticalAlign: "bottom"}}>
              <MenuItem value="relevance" label="Relevance" primaryText="Relevance" />
              <MenuItem value="date" label="Oldest first" primaryText="Oldest first" />
              <MenuItem value="date_descending" label="Newest first" primaryText="Newest first" />
            </DropDownMenu>
          </div>

          {facet_list2}

          {/*
            this.props.facets.length === 0 ? null :
            (
              <div style={{marginTop: 20}}><a href="#" onClick={() => this.props.actions.updateFacetBatch({})}>Reset Filters</a></div>
            )*/
          }
          {
              this.props.facets.length === 0 ? null :
              (
                  <button className="btn" onClick={() => this.props.actions.updateFacetBatch({})}>
                      <div id = "btn_container">
                          <img src="../../../static/images/reset-filters.jpg" style={{width:"30px",height:"30px"}}/>
                      </div>
                      <span>RESET FILTERS</span>
                  </button>
              )
          }
        </div>
      </div>);
  }
}

Open in new window

Avatar of Zakaria Acharki
Zakaria Acharki
Flag of Morocco image

I'm sorry but the posted code not helping too much, If you can produce the generated HTML code I could suggest a pure JS solution.
Avatar of coder

ASKER

Hi Zakaria,

      Thanks for your response.   It is an react redux application.  Basically, I am updating the state(facets) and this state should be reflected(changes) on the GUI.  I had created Actions, reducers and also updated the react components code.  I had checked the console logs on actions and reducers, it is working fine.  Now the only problem is the state (facets) is updating the components.  Once the state is updated, GUI will change.  

With Many thanks,

Bharath AK
Avatar of coder

ASKER

Hi there,

Please refer the screen shot for reference

 

in this react application left hand side items are stored in state called facets.  It one of text boxes I had typed Abor when I type Abor or aborigines it should filter the list of checkboxes based on what I type in the textboxes.  All complete list is stored in the state. facets.  I want to search this state.facets and filter as I type in the textbox and gui (the list of checkboxes) should change to filtered list as I type in the text box.

Could you please help in, how to do it in redux.  

It that search component

@connect ((state) => {
      return {
      facets: state.search.facets,
      }
},(dispatch) => {
     actions: bindActioncreators(action,dispatch),
 }
})

export default class SearchOptions extends Component {
  constructor(props) {
     super(props);
     //this.updateFacet = this.updateFacet.bind(this);
     this.onInputBoxChange = this.onInputBoxChange.bind(this);
  }


 onInputBoxChange(e,items,key) {
     var keysList = items.filter(i => i.value.toLowerCase().indexOf(e.target.value.toLowerCase().toString()) >= 0 ? true : false);
     var lowercaseItems = Array.from(keysList);
     var finalKeyList = [];
     items.forEach((e1)=>lowercaseItems.forEach((e2)=>{
       var item1 = e1.value;
       var item2 = e1.value.toLowerCase();
       if(item2 === e2.value) {finalKeyList.push(e1)}}));

     var facet = {
                   Key: key,
                   items: finalKeyList,
                 };

     var newFacets = Array.from(this.props.facets);
     var updatedFacets = [];

     newFacets.map((i)=> {
      if(i.key === facet.Key)
          updatedFacets.push(facet);
      else
          updatedFacets.push(i);
     });

     //this.setState(facets);
     this.props.actions.updateFacetsOnChange(updatedFacets);
}

 const inputBox = (<div className="inner-addon left-addon">
                             <i className="glyphicon gluphicon-search form-control-search"></i>
                             <input type="text" name={inputName} placeholder={inputName} style={{marginBottom:10}} onChange=
                                 {(e) => this.onInputBoxChange(e,i.items,i.key)} className="form-control" />
                          </div>);

Open in new window


in action/search.js

export function updateFacetsOnChange(facets) {
  return {type: SEARCH_UPDATE_FACETS_ONCHANGE,facets};
}

Open in new window


on reducer/search.js

export default function search(state=initialState, action) {
  switch (action.type) {

case SEARCH_UPDATE_FACETS_ONCHANGE:
      console.log('reducer - update facets ',action.facets);
      return action.facets;

    default:
      return state;
  }
}

Open in new window



But this code is not working.  Facets is not updated on the GUI I am able to see on the reducers and actions the updated list of items for checkboxes but not able to update on the components.

secondly I am doing all the update logic on components and afterward I call the action with updated list.  Please suggest me where should I code the updated logic list,  in the component, or actions or on the reducers?

Please suggest me and help me in resolving this issue.

With Many thanks,

Bharath AK
Avatar of coder

ASKER

Hi Zakaria,

  Application is built with reacts, redux and with some Django,  Javascript is pretty less, All reactjs redux converted to a javascript file with webpack.

do you need that javascript file?  Its pretty complex to analyze that javascript file?  the file has the code of more than 10000 lines

Secondly,  I am able to get the filter list when I type in the keyword.  I get the filtered list but not able to update the gui.
When I type Abor I can get aborgines list of 3 keywords for subject. you can see from the console logs windows.  But not able the list as 3 checkboxes below Abor search keyword.

Please refer the embeded image for reference.

 

Please help me in resolving this issue.

With Many thanks,

Bharath AK
Avatar of coder

ASKER

Hi Zakaria,

Please find attached screen capture for reference


I want to filter the keyword or location based on what I type on the input box with the list in the modal dialog.

I am able to get the filtered list you can see from following console log.  but I am not able to update the GUI(make the filtered list of Checkboxes) on the main window.

 

When I type Abor on the input box it filters with the complete list base on the model dialog and gets the list. but not able to update the GUI on the main screen with the list of checkboxes.

you can see the html code for displaying  "by keyword" div

<div style="margin-top:15px;" data-reactid="863"><div data-reactid="864"><div style="text-transform:capitalize;margin-bottom:8px;display:inline-block;" data-reactid="865">
	<span data-reactid="866"><!-- react-text: 867 --> By <!-- /react-text --><!-- react-text: 868 -->keyword<!-- /react-text --><!-- react-text: 869 --> <!-- /react-text --></span></div><div class="inner-addon left-addon" data-reactid="870">
	<i class="glyphicon gluphicon-search form-control-search" data-reactid="871"></i>
	<input type="text" name="Keyword" placeholder="Keyword" style="margin-bottom:10px;" class="form-control" data-reactid="872">
	</div>
	</div>
	<div style="margin-left:10px;" data-reactid="873"><label class="full-checkbox" data-reactid="874"><!-- react-text: 875 --> <!-- /react-text --><!-- react-text: 876 -->Aboriginal peoples (australians) (2)<!-- /react-text --><input type="checkbox" value="aboriginal peoples (australians)" data-reactid="877">
	<span class="checkmark" data-reactid="878"></span></label><label class="full-checkbox" data-reactid="879"><!-- react-text: 880 --> <!-- /react-text --><!-- react-text: 881 -->Agriculture (1)<!-- /react-text -->
	<input type="checkbox" value="agriculture" data-reactid="882">
	<span class="checkmark" data-reactid="883"></span></label>
	<label class="full-checkbox" data-reactid="884"><!-- react-text: 885 --> <!-- /react-text --><!-- react-text: 886 -->Australian newspapers (1)<!-- /react-text --><input type="checkbox" value="australian newspapers" data-reactid="887">
	<span class="checkmark" data-reactid="888"></span></label></div>
	<a href="#" style="margin-left:10px;margin-top:5px;font-size:14px;font-weight:bold;color:#C25518;" data-reactid="889">MORE</a></div>
	
	<div style="margin-top:15px;" data-reactid="890"><div data-reactid="891">
	<div style="text-transform:capitalize;margin-bottom:8px;display:inline-block;" data-reactid="892"><span data-reactid="893"><!-- react-text: 894 --> By <!-- /react-text --><!-- react-text: 895 -->contributor<!-- /react-text --><!-- react-text: 896 --> <!-- /react-text --></span></div><div class="inner-addon left-addon" data-reactid="897">
	<i class="glyphicon gluphicon-search form-control-search" data-reactid="898"></i><input type="text" name="Contributor" placeholder="Contributor" style="margin-bottom:10px;" class="form-control" data-reactid="899"></div></div><div style="margin-left:10px;" data-reactid="900">
	<label class="full-checkbox" data-reactid="901"><!-- react-text: 902 --> <!-- /react-text --><!-- react-text: 903 -->Aagaard, jane (1)<!-- /react-text --><input type="checkbox" value="aagaard, jane" data-reactid="904"><span class="checkmark" data-reactid="905"></span></label>
	<label class="full-checkbox" data-reactid="906"><!-- react-text: 907 --> <!-- /react-text --><!-- react-text: 908 -->Carney, jodeen (1)<!-- /react-text --><input type="checkbox" value="carney, jodeen" data-reactid="909">
	<span class="checkmark" data-reactid="910"></span></label><label class="full-checkbox" data-reactid="911"><!-- react-text: 912 --> <!-- /react-text --><!-- react-text: 913 -->Cheater, graeme, 1955- (1)<!-- /react-text -->
	<input type="checkbox" value="cheater, graeme, 1955-" data-reactid="914"><span class="checkmark" data-reactid="915">
	</span></label>
	</div>
	<a href="#" style="margin-left:10px;margin-top:5px;font-size:14px;font-weight:bold;color:#C25518;" data-reactid="916">MORE</a>
	</div>

Open in new window


Please get back to me if you are unclear with the problem.

Thanks your help

With Kind Regards,

Bharath AK
ASKER CERTIFIED SOLUTION
Avatar of coder
coder
Flag of Australia image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial