NativeBase multiple icons in InputGroup

2.8k views Asked by At

I'm trying to make an InputGroup that has two icons OR one icon and one button.

One icon should be used to check if the input field is empty or not (got that working). The other icon OR button should be used to "inject" some text into the Input field.

Currently my code looks like this:

import React, { Component } from 'react'
import { Content, List, InputGroup, Input, Icon, Button } from 'native-base'
export default class AddEquipment extends Component {
  constructor(props) {
    super(props)

    this.state = {
      parameters:  {
        one: {value:"", hint: "One"},
        two: {value:"", hint: "Two"},
        three: {value:"Valid", hint: "Three"}
      }
    }

    this.updateParameter = this.updateParameter.bind(this)
    this.validationStyle = this.validationStyle.bind(this)
  }

  componentDidMount() {

  }

  updateParameter(key, value) {
    newState = {...this.state}
    newState.parameters[key].value = value
    this.setState = newState;
  }

  validationStyle(text) {
    color = text === "" ? "#b03939" : "#649370"
    return (
      { marginRight:25, color
      }
    )
  }

  render () {
    return (
      <Content>
        { Object
          .keys(this.state.parameters)
          .map( key =>
            <InputGroup
              key={`${key}_InputGroup`}
              iconRight
              borderType='regular'
              style={{margin:5}}
              >

              <Input
                placeholder={this.state.parameters[key].hint}
                onChangeText={(text) => {
                  console.log(this.state.parameters)
                  this.updateParameter(key, text)} }
                value={key.value}
              />

              <Icon
                key={`${key}_validIcon`}
                name={ this.state.parameters[key].value === "" ? 'ios-alert' : 'ios-checkmark-circle'}
                style={ this.validationStyle(this.state.parameters[key].value) }
              />

              <Icon
                key={`${key}_injectNA`}
                name='ios-beer'
                onPress={() => this.updateParameter(key, "Cheers!") }/>

            </InputGroup>
          )
        }
      </Content>
    )
  }
}

Which gives me the following result

output

First issue

As you can see I have trouble getting the other icon appear - it doesn't seem to lie behind the first.

A button would be as good, but it always drops below the Input and not next to it. Styling is not my strongest style - hence why I use the awesome framework NativeBase

Second issue

Another problem I have is that the validation does not seem to change icon and color after the state is being updated. Seems like the style are loaded only once.

1

There are 1 answers

5
Max Vorobjev On BEST ANSWER

on the first issue would you consider validity icon in front? InputGroup can dispay maximum two icons: before and after text input, see code below.

on the second issue it's caused that you assign value to the state, while in React you should call this.setState(newState), see reference

another issue is accessing to the object key's value by key.value, while key is just a string (key name), while real object accessed by this.state.parameters[key]

Following code fixes all mentioned issues (but validity icon is on the left):

import React, { Component } from 'react'
import { Content, List, InputGroup, Input, Icon, Button } from 'native-base'

const errorStyle = {color: "#b03939"}
const validStyle = {color: "#649370"}

export default class AddEquipment extends Component {
  constructor(props) {
    super(props)

    this.state = {
      parameters:  {
        one: {value:"", hint: "One"},
        two: {value:"", hint: "Two"},
        three: {value:"Valid", hint: "Three"}
      }
    }

    this.updateParameter = this.updateParameter.bind(this)
  }

  componentDidMount() {

  }

  updateParameter(key, value) {
    let newState = {...this.state}
    newState.parameters[key].value = value
    this.setState(newState);
  }

  static validationStyle(text) {
    return text === "" ? errorStyle : validStyle;
  }

  render () {
    return (
      <Content>
        { Object
          .keys(this.state.parameters)
          .map( key =>
            <InputGroup
              key={`${key}_InputGroup`}
              borderType='regular'
              style={{margin:5}}
              >

              <Icon
                  key={`${key}_validIcon`}
                  name={ this.state.parameters[key].value === "" ? 'ios-alert' : 'ios-checkmark-circle'}
                  style={ AddEquipment.validationStyle(this.state.parameters[key].value) }
                />

              <Input
                placeholder={this.state.parameters[key].hint}
                onChangeText={(text) => {
                  console.log(this.state.parameters)
                  this.updateParameter(key, text)} }
                value={this.state.parameters[key].value}
              />

              <Icon
                key={`${key}_injectNA`}
                name='ios-beer'
                onPress={() => this.updateParameter(key, "Cheers!") }/>

            </InputGroup>

          )
        }
      </Content>
    )
  }
}