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

coder
coder used Ask the Experts™
on
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.

to handle onChange event of dynamically created input boxes
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

Comment
Watch Question

Do more with

Expert Office
EXPERT OFFICE® is a registered trademark of EXPERTS EXCHANGE®
Zakaria AcharkiAnalyst Developer
Distinguished Expert 2018

Commented:
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.
coderdeveloper

Author

Commented:
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
coderdeveloper

Author

Commented:
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
Ensure you’re charging the right price for your IT

Do you wonder if your IT business is truly profitable or if you should raise your prices? Learn how to calculate your overhead burden using our free interactive tool and use it to determine the right price for your IT services. Start calculating Now!

coderdeveloper

Author

Commented:
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
coderdeveloper

Author

Commented:
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
developer
Commented:
Hi Zakaria,

I was not updating the state on the reducer.

once I update the state it got reflected on the main screen.

the code I had done to update the state is

return {...state,facets:updatedFacets};

Open in new window



in the component, file state is received the following code

@connect((state) => {
  return {
    facets: state.search.facets,
    initialFacets: state.search.initialFacets,
    thumbnailSize: state.search.thumbnailSize,
    sortOrder: state.search.sortOrder,
  }
}, (dispatch) => {
  return {
    actions: bindActionCreators(actions, dispatch),
  }
})

Open in new window



I missed updated the state on the reducers once updated it started to reflect on the components then it started working.

Initially, I misunderstood that, you are asking for javascript code.  apologies for the confusion.

now it is working fine.

Thanks for your help.

with kind regards,

Bharath AK

Do more with

Expert Office
Submit tech questions to Ask the Experts™ at any time to receive solutions, advice, and new ideas from leading industry professionals.

Start 7-Day Free Trial