I was just wondering what path to take to implement what the title says using your beautiful library.!
The simplest way would be to write a custom template:
(pseudo code)
class MyPasswordComponent extends React.Component {
state = {
passwordDisplayed: false
}
toggleDisplay() {
this.setState({ passwordDisplayed: !this.state.passwordDisplayed })
}
render() {
return <div onClick={this.toggleDisplay.bind(this)}>...your input here..</div>
}
}
// override the default template https://github.com/gcanti/tcomb-form-native/blob/master/lib/templates/bootstrap/textbox.js#L4
function myPasswordTemplate(locals) {
return ...<MyPasswordComponent /> ...
}
...
const Type = t.struct({
password: t.String
})
const options = {
fields: {
password: {
template: myPasswordTemplate
}
}
}
Thank you!
Ok for people looking for this in the future, I have created it and it looks like this:

PasswordTemplate.js:
import React from 'react';
import { View, Text, TextInput, TouchableOpacity } from 'react-native';
function passwordTextbox(locals) {
if (locals.hidden) {
return null;
}
var stylesheet = locals.stylesheet;
var formGroupStyle = stylesheet.formGroup.normal;
var controlLabelStyle = stylesheet.controlLabel.normal;
var passwordTextboxStyleContainer = stylesheet.passwordTextboxStyleContainer.normal;
var passwordTextboxBtn = stylesheet.passwordTextboxBtn;
var passwordTextboxBtnTxt = stylesheet.passwordTextboxBtnTxt;
var passwordTextboxStyle = stylesheet.textbox.normal;
var helpBlockStyle = stylesheet.helpBlock.normal;
var errorBlockStyle = stylesheet.errorBlock;
if (locals.hasError) {
formGroupStyle = stylesheet.formGroup.error;
passwordTextboxStyleContainer = stylesheet.passwordTextboxStyleContainer.error;
controlLabelStyle = stylesheet.controlLabel.error;
passwordTextboxStyle = stylesheet.textbox.error;
helpBlockStyle = stylesheet.helpBlock.error;
}
if (locals.editable === false) {
passwordTextboxStyle = stylesheet.textbox.notEditable;
passwordTextboxStyleContainer = stylesheet.passwordTextboxStyleContainer.notEditable;
}
var label = locals.label ? <Text style={controlLabelStyle}>{locals.label}</Text> : null;
var help = locals.help ? <Text style={helpBlockStyle}>{locals.help}</Text> : null;
var error = locals.hasError && locals.error ? <Text accessibilityLiveRegion="polite" style={errorBlockStyle}>{locals.error}</Text> : null;
return (
<View style={formGroupStyle}>
{label}
<View style={[{flexDirection:'row', justifyContent:'center', borderColor: 'black', borderRadius:2, borderWidth: 1,}, passwordTextboxStyleContainer]}>
<View style={{flex:1}}>
<TextInput
accessibilityLabel={locals.label}
ref="input"
autoCapitalize={locals.autoCapitalize}
autoCorrect={locals.autoCorrect}
autoFocus={locals.autoFocus}
blurOnSubmit={locals.blurOnSubmit}
editable={locals.editable}
keyboardType={locals.keyboardType}
maxLength={locals.maxLength}
multiline={locals.multiline}
onBlur={locals.onBlur}
onEndEditing={locals.onEndEditing}
onFocus={locals.onFocus}
onLayout={locals.onLayout}
onSelectionChange={locals.onSelectionChange}
onSubmitEditing={locals.onSubmitEditing}
placeholderTextColor={locals.placeholderTextColor}
secureTextEntry={locals.secureTextEntry}
selectTextOnFocus={locals.selectTextOnFocus}
selectionColor={locals.selectionColor}
numberOfLines={locals.numberOfLines}
underlineColorAndroid={locals.underlineColorAndroid}
clearButtonMode={locals.clearButtonMode}
clearTextOnFocus={locals.clearTextOnFocus}
enablesReturnKeyAutomatically={locals.enablesReturnKeyAutomatically}
keyboardAppearance={locals.keyboardAppearance}
onKeyPress={locals.onKeyPress}
returnKeyType={locals.returnKeyType}
selectionState={locals.selectionState}
onChangeText={(value) => locals.onChange(value)}
onChange={locals.onChangeNative}
placeholder={locals.placeholder}
style={[{flex:1},passwordTextboxStyle,{ borderWidth: 0}] }
value={locals.value}
/>
</View>
<TouchableOpacity style={[{justifyContent:'center', paddingHorizontal:5}, passwordTextboxBtn]} onPress={(e)=>{if(!!locals.config.onShowPasswordClicked){locals.config.onShowPasswordClicked(locals.config.passwordHidden)}}}>
<Text style={passwordTextboxBtnTxt}>{locals.config.passwordHidden===false?"Hide":"Show"}</Text>
</TouchableOpacity>
</View>
{help}
{error}
</View>
);
}
module.exports = passwordTextbox;
In order to use it, you have to provide the stylesheet and options for it like so:
let options = {
stylesheet: stylesheet,
auto: 'placeholders',
fields: {
password: {
template: PasswordTemplate,
label: 'Create a Password',
maxLength: 20,
secureTextEntry: !this.props.authFormFields.showPassword,
editable: !this.props.isFetchingAuth,
hasError: this.props.authFormFields.passwordHasError,
error: 'Password length 6-20 characters, containing both a number and a capital letter.',
placeholder: '*******',
returnKeyType: 'next',
onSubmitEditing: this.onPasswordFinishedEditing,
blurOnSubmit : true,
underlineColorAndroid: Colors.accentColor,
autoCorrect: false,
autoCapitalize:'none',
placeholderTextColor: Colors.secondaryTextColor,
// autoFocus: true,
config:{
passwordHidden: true,
onShowPasswordClicked: this.onPasswordShowClicked.bind(this)
}
},
}
};
and style it something like this:
const INPUT_COLOR = Colors.thirdTextColor;
const DISABLED_COLOR = '#777777';
const DISABLED_BACKGROUND_COLOR = '#eeeeee';
const FONT_SIZE = 11;
const FONT_WEIGHT = '500';
const stylesheet = Object.freeze({
fieldset: {
flexDirection: 'column'
},
// the style applied to the container of all inputs
formGroup: {
normal: {
flex:0,
marginBottom: 10
},
error: {
flex:0,
marginBottom: 10
}
},
controlLabel: {
normal: {
// backgroundColor:'red',
color: Colors.fourthTextColor,
fontSize: 11,
marginBottom: 7,
fontWeight: FONT_WEIGHT
},
// the style applied when a validation error occours
error: {
color: Colors.errorTextColor,
fontSize: FONT_SIZE,
marginBottom: 7,
fontWeight: FONT_WEIGHT
}
},
helpBlock: {
normal: {
color: Colors.helpTextColor,
fontSize: FONT_SIZE,
marginBottom: 2
},
// the style applied when a validation error occours
error: {
color: Colors.helpTextColor,
fontSize: FONT_SIZE,
marginBottom: 2
}
},
errorBlock: {
fontSize: 12,
justifyContent: 'center',
textAlign: 'center',
color: Colors.errorTextColor
},
textbox: {
normal: {
color: INPUT_COLOR,
fontSize: 10,
height: 45,
padding: 7,
borderRadius: 4,
borderColor: Colors.mainBorderColor,
borderWidth: 1,
// marginBottom: 5
},
// the style applied when a validation error occours
error: {
color: INPUT_COLOR,
fontSize: FONT_SIZE,
height: 45,
padding: 7,
borderRadius: 4,
borderColor: Colors.errorTextColor,
borderWidth: 1,
// marginBottom: 5
},
// the style applied when the textbox is not editable
notEditable: {
fontSize: FONT_SIZE,
height: 36,
padding: 7,
borderRadius: 4,
borderColor: Colors.mainBorderColor,
borderWidth: 1,
// marginBottom: 5,
color: DISABLED_COLOR,
backgroundColor: DISABLED_BACKGROUND_COLOR
}
},
passwordTextboxStyleContainer:{
normal: {
// height: 45,
// padding: 7,
borderRadius: 4,
borderColor: Colors.mainBorderColor,
borderWidth: 1,
// marginBottom: 5
},
// the style applied when a validation error occours
error: {
borderRadius: 4,
borderColor: Colors.errorTextColor,
borderWidth: 1,
// marginBottom: 5
},
// the style applied when the textbox is not editable
notEditable: {
borderRadius: 4,
borderColor: Colors.mainBorderColor,
borderWidth: 1,
backgroundColor: DISABLED_BACKGROUND_COLOR
}
},
passwordTextboxBtn:{
paddingHorizontal:w*.025
},
passwordTextboxBtnTxt:{
fontSize: 12,
color: Colors.primaryColor
}
});
Then finally:
let passwordForm = t.struct({
password: t.String
});
return (
<Form ref="form"
type={passwordForm}
options={options}
value={this.props.value}
onChange={this.props.onChange}
/>
);
@gcanti if you find time you could perhaps add it to your library, because a password input with such a show/hide label button I think is necessary to lots of people.
@SudoPlz I want to keep this library lean, a useful component like yours may be published as a standalone component though
@SudoPlz - how do i use it in my signing page?
this is my page:
import React from 'react';
import {View,Text,Image,TextInput,TouchableOpacity,Dimensions,StatusBar,Platform} from 'react-native';
var StyleSheet = require('WS1StyleSheet');
import {connect} from 'react-redux';
import t from 'react-native-i18n';
import Icon from 'react-native-vector-icons/MaterialIcons';
var f = require('tcomb-form-native');
var Form = f.form.Form;
// here we are: define your domain model
var LoginForm = f.struct({
email: f.String, // a required string
password: f.String, // a required string
});
import {mergeFormCss} from 'common/formCss';
import {textbox} from 'lib/MKTextbox';
var options = {
stylesheet:mergeFormCss({
textbox: {
normal: {
textAlign:t.t('dir') == 'rtl' && Platform.OS == 'android'?'right':'left',
height: 30, // have to do it on iOS
color:'white',
},
}
},'flat'),
fields: {
email: {
placeholder : t.t('Email'),
auto: 'placeholders',
error: t.t('Email is empty'),
template: (locals) => textbox(locals ,
},
password: {
placeholder : t.t('Password'),
auto: 'placeholders',
error: t.t('Password is empty'),
password:true,
secureTextEntry:true,
template: (locals) => textbox(locals,
}
}
};
//Load data
var {
loadShipments,
loadOrders
} = require('./../../models/actions');
var Signin = React.createClass({
getInitialState() {
return {
value:{
email : '',
password : '',
},
errorMessage : '',
loading: false
};
},
componentWillMount(){
StatusBar.setBarStyle('light-content');
},
onChange(value) {
this.setState({value});
},
render: function(){
return (
<View style={[styles.headerWrapper,this.border('red')]}>
<Text style={{textAlign: 'center',color:'white',fontSize:25,marginTop:5}}>{t.t('Login')}</Text>
</View>
<View style={[styles.formWrapper,this.border('green')]}>
<View style={[styles.formWrapper_form,,this.border('yellow')]}>
<View style={[styles.formlogin]}>
{this.loginform()}
</View>
</View>
<View style={[styles.formWrapper_button,this.border('green')]}>
{this.loginbutton()}
</View>
</View>
</View>
);
},
loginform: function(){
return
<Form
ref="form"
type={LoginForm}
value={this.state.value}
onChange={this.onChange}
options={options}
/>
</View>
},
loginbutton: function(){
return
<AS1Button
isLoading={this.state.loading}
textStyle={{fontSize: 26,color:'white'}}
style={{backgroundColor:'#F66A3B',height:43,width:300}}
onPress={this.logInButton}
>
{t.t('Login')}
</WS1Button>
</View>
},
border: function(color){
return {
borderColor:color,
borderWidth: 0,
}
},
logInButton() {
var value = this.refs.form.getValue();
if (value) {
this.setState({loading:true});
Api.login({
email:value.email,
password:value.password
})
this.setState({loading:false});
}
},
});
var styles = StyleSheet.create({
container: {
flex:1,
});
module.exports = connect()(Signin);
@abuammar I believe you're not passing the right template.
var options = {
stylesheet: mergeFormCss({
textbox: {
normal: {
textAlign: t.t('dir') == 'rtl' && Platform.OS == 'android' ? 'right' : 'left',
height: 30, // have to do it on iOS
color: 'white',
},
}
}, 'flat'),
fields: {
email: {
placeholder: t.t('Email'),
auto: 'placeholders',
error: t.t('Email is empty'),
template: (locals) => textbox(locals, ),
},
password: {
placeholder: t.t('Password'),
auto: 'placeholders',
error: t.t('Password is empty'),
password: true,
secureTextEntry: true,
template: (locals) => textbox(locals, ), // <--- Here you have to pass the PasswordTemplate
}
}
};
already in lib for hide and show password? @gcanti
bro @SudoPlz how to change value passwordHidden and secureTextEntry when click show/hide?
@otikindriyana it's been 4 years, I don't even remember TBH, and we no longer use this library :/
already solved
add:
`
onPasswordShowClicked(){
if(this.state.options.fields.confirmPassword.secureTextEntry == true){
var options = t.update(this.state.options, {
fields: {
confirmPassword: {
secureTextEntry: {'$set': false},
config:{
passwordHidden: {'$set': false},
}
}
}
});
this.setState({options: options});
}else if(this.state.options.fields.confirmPassword.secureTextEntry == false){
var options = t.update(this.state.options, {
fields: {
confirmPassword: {
secureTextEntry: {'$set': true},
config:{
passwordHidden: {'$set': true},
}
}
}
});
this.setState({options: options});
}
}
`
Most helpful comment
Ok for people looking for this in the future, I have created it and it looks like this:
PasswordTemplate.js:In order to use it, you have to provide the stylesheet and options for it like so:
and style it something like this:
Then finally: