Reputation: 2034
i'm trying to update a datasource and i have checked the below url
https://github.com/facebook/react-native/issues/4104 https://github.com/mobxjs/mobx/issues/569
i tired creating a new array and then updating it but i'm not sure how to update the datasource.
On change of the checkbox i'm updating the object and assigning it to the datatsource, but the checkbox is not updating.
Below is the code i have tried.
constructor
constructor() {
super();
const ds = new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2});
this.state = {
modalVisible: false,
todoText:'',
todoListArray:[],
dataSource: ds
};
}
Listview
<ListView
dataSource={this.state.dataSource}
renderRow={this.generateRow.bind(this)}
/>
generateRow=(rowData, sectionID, rowID, highlightRow) => {
return (
<View style={styles.listItem}>
<CheckBox
label=''
checked={rowData.isCompleted}
onChange={() => {this.changeisCompleted(this,rowID)}}
/>
<Text style={styles.listItemText}>{rowData.text}</Text>
</View>
);
}
/*When Checkbox is clicked*/
changeisCompleted=(rowData,rowId)=>{
var newDs = [];
newDs = this.state.todoListArray.slice();
newDs[rowId].isCompleted =!newDs[rowId].isCompleted;
alert(JSON.stringify(newDs));
this.setState({
dataSource: this.state.dataSource.cloneWithRows(newDs)
})
}
/*adding new item to listView*/
addTodo = () => {
var todoObj={
"text":this.state.todoText,
"isCompleted":false
}
this.state.todoListArray.push(todoObj);
this.closeModal();
this.setState({todoText: ''});
this.setState({
dataSource: this.state.dataSource.cloneWithRows(this.state.todoListArray)
})
}
adding the entire file:
/**
* Sample React Native App
* https://github.com/facebook/react-native
* @flow
*/
import React, { Component } from 'react';
import {
AppRegistry,
StyleSheet,
Text,
View,
ToolbarAndroid,
Modal,
Button,
TextInput,
Image,
ListView,
TouchableHighlight
} from 'react-native';
import CheckBox from 'react-native-checkbox';
{/*import AddToDoModal from './src/components/AddTodoModal.js';*/}
export default class FirstReactNativeApp extends Component {
constructor() {
super();
const ds = new ListView.DataSource({rowHasChanged: (row1, row2) => row1 !== row2});
this.state = {
modalVisible: false,
todoText:'',
todoListArray:[],
dataSource: ds,
};
}
componentDidMount = () => function() {
}
openModal = () => {
this.setState({modalVisible: true});
}
closeModal = () => {
this.setState({modalVisible: false});
}
setModalVisible=(visible) =>{
this.setState({modalVisible: visible});
}
changeisCompleted=(rowData,rowId)=>{
var newDs = [];
newDs = this.state.todoListArray.slice();
newDs[rowId].isCompleted =!newDs[rowId].isCompleted;
newDs[rowId].text ="Changed";
alert(JSON.stringify(newDs));
//this.state.todoListArray=newDs;
//alert("listArray=="+JSON.stringify(this.state.todoListArray))
this.setState({
todoListArray:newDs,
dataSource: this.state.dataSource.cloneWithRows(newDs)
})
}
addTodo = () => {
var todoObj={
"text":this.state.todoText,
"isCompleted":false
}
this.state.todoListArray.push(todoObj);
this.closeModal();
this.setState({todoText: ''});
this.setState({
dataSource: this.state.dataSource.cloneWithRows(this.state.todoListArray)
})
}
generateRow=(rowData, sectionID, rowID, highlightRow) => {
return (
<View style={styles.listItem}>
<CheckBox
label=''
checked={rowData.isCompleted}
onChange={() => {this.changeisCompleted(this,rowID)}}
/>
<Text style={styles.listItemText}>{rowData.text}</Text>
</View>
);
}
render() {
return (
<View>
<ToolbarAndroid
style={styles.toolbar}
title="ToDo List"
actions={[{title: 'Add', icon: require('./img/add.png'), show: 'always'}]}
onActionSelected={this.openModal}
/>
<ListView
dataSource={this.state.dataSource}
renderRow={this.generateRow.bind(this)}
/>
<Modal
animationType={"none"}
transparent={false}
visible={this.state.modalVisible}
onRequestClose={() => {alert("Modal has been closed.")}} >
<View style={styles.container}>
<View style={styles.modalContent}>
{/*this is icon button*/}
<TouchableHighlight style={{justifyContent:'flex-end',flexDirection:'row'}} onPress={this.closeModal}>
<Image
style={styles.closeButton}
source={require('./img/close.png')}
/>
</TouchableHighlight>
<Text style={{textAlign:'center',marginBottom:30}}>Add New ToDo</Text>
<TextInput
style={{height: 40, borderColor: 'gray', borderWidth: 1,marginBottom:10}}
placeholder='Enter ToDo'
onChangeText={(todoText) => this.setState({todoText})}
value={this.state.todoText}
/>
<Button
onPress={()=> {this.addTodo()}}
title='Add ToDo'
color='#1e90ff'/>
</View>
</View>
</Modal>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#000000',
opacity:0.8
},
welcome: {
fontSize: 20,
textAlign: 'center',
margin: 10,
},
instructions: {
textAlign: 'center',
color: '#333333',
marginBottom: 5,
},
toolbar: {
height:55,
backgroundColor: '#1e90ff',
},
modal: {
height:50,
marginVertical:22,
},
modalContent: {
backgroundColor: '#ffffff',
height:300,
width:300,
borderRadius:3,
paddingVertical:10,
paddingHorizontal:20,
},
closeButton: {
height:30,
width:30,
},
listItem: {
backgroundColor: '#ffffff',
paddingLeft:10,
height:50,
borderBottomWidth:1,
borderColor: '#000000',
flex:1,
flexDirection:'row',
alignItems:'center',
},
listItemText: {
fontSize:20,
}
});
AppRegistry.registerComponent('FirstReactNativeApp', () => FirstReactNativeApp);
Upvotes: 0
Views: 1122
Reputation: 2034
So after a lot of reading and changes the listview is now updating. According to this post
Changes the ds declaration to:
this.ds = new ListView.DataSource({rowHasChanged: (row1, row2) => row1 !== row2});
So changed my changeisComplete method
changeisCompleted=(rowData,rowId)=>{
var newDs = [];
newDs = this.state.todoListArray.slice();
newDs[rowId].isCompleted =!newDs[rowId].isCompleted;
this.setState({
dataSource: this.ds.cloneWithRows(this.state.todoListArray),
todoListArray:newDs
})
}
I'm not sure if this is the right way to do this,but anyway it works and now the checkbox is getting changed
Thanks
Upvotes: 1
Reputation: 9978
You have two problems. First, you are setting the datasource to the result of the cloning. Just use {this.state.dataSource}:
dataSource={this.state.dataSource.cloneWithRows(this.state.todoListArray)}
because you are setting the DS result and not linking the Datasource. Also, you don't need the double data in the state (The array and also the datasource).
And the second and most important, you are not actually setting the state. Only in the constructor you can set it like this: this.state.
After that, you can only set it like this:
this.setState({dataSource: this.state.dataSource.cloneWithRows(updatedArray)});
Upvotes: 0