todo example
This commit is contained in:
parent
95189a3a37
commit
ccd2301d9e
|
@ -9,90 +9,196 @@ var React = require('react-native');
|
||||||
var {
|
var {
|
||||||
AppRegistry,
|
AppRegistry,
|
||||||
StyleSheet,
|
StyleSheet,
|
||||||
|
NavigatorIOS,
|
||||||
|
AlertIOS,
|
||||||
ListView,
|
ListView,
|
||||||
|
TouchableHighlight,
|
||||||
Text,
|
Text,
|
||||||
|
TextInput,
|
||||||
View,
|
View,
|
||||||
} = React;
|
} = React;
|
||||||
|
|
||||||
var Person = function() {}
|
var TodoItemSchema = {
|
||||||
Person.prototype.schema = {
|
name: 'Todo',
|
||||||
name: 'Person',
|
|
||||||
properties: [
|
properties: [
|
||||||
{name: 'name', type: RealmType.String},
|
{name: 'text', type: RealmType.String},
|
||||||
{name: 'age', type: RealmType.Double},
|
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
Person.prototype.capitalName = function() {
|
var TodoListSchmea = {
|
||||||
return this.name.toUpperCase();
|
name: 'TodoList',
|
||||||
|
properties: [
|
||||||
|
{name: 'name', type: RealmType.String},
|
||||||
|
{name: 'items', type: RealmType.Array, objectType: 'Todo'}
|
||||||
|
]
|
||||||
};
|
};
|
||||||
|
|
||||||
var RealmReact = React.createClass({
|
console.log(Realm.defaultPath);
|
||||||
getInitialState: function() {
|
var realm = new Realm({schema: [TodoItemSchema, TodoListSchmea]});
|
||||||
return {
|
|
||||||
dataSource: new ListView.DataSource({
|
|
||||||
rowHasChanged: (row1, row2) => row1 !== row2,
|
|
||||||
}),
|
|
||||||
};
|
|
||||||
},
|
|
||||||
renderPerson: function(person) {
|
|
||||||
return (
|
|
||||||
<View style={styles.container}>
|
|
||||||
<Text>{person.capitalName()} {person.age}</Text>
|
|
||||||
</View>
|
|
||||||
);
|
|
||||||
},
|
|
||||||
render: function() {
|
|
||||||
return (
|
|
||||||
<View style={styles.container}>
|
|
||||||
<ListView dataSource={this.state.dataSource} renderRow={this.renderPerson} style={styles.listView}/>
|
|
||||||
<Text style={styles.instructions}>
|
|
||||||
Press Cmd+R to reload,{'\n'}
|
|
||||||
Cmd+Control+Z for dev menu
|
|
||||||
</Text>
|
|
||||||
</View>
|
|
||||||
);
|
|
||||||
},
|
|
||||||
componentDidMount: function() {
|
|
||||||
var realm = new Realm({schema: [Person]});
|
|
||||||
var objects = realm.objects('Person');
|
|
||||||
|
|
||||||
console.log(realm.path);
|
|
||||||
|
|
||||||
if (objects.length < 4) {
|
class Edit extends React.Component {
|
||||||
realm.write(function() {
|
componentWillMount() {
|
||||||
realm.create('Person', ['Joe', 26]);
|
this.setState({text: this.props.text});
|
||||||
realm.create('Person', ['Sam', 20]);
|
|
||||||
realm.create('Person', ['Alexander', 37]);
|
|
||||||
realm.create('Person', ['Ari', 34]);
|
|
||||||
realm.create('Person', {'name': 'Bjarne', age: 37});
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var olderThan30 = realm.objects('Person', 'age > 30');
|
save() {
|
||||||
console.log(olderThan30.length);
|
var list = this.props.list;
|
||||||
|
var id = this.props.todoId;
|
||||||
|
var text = this.state.text;
|
||||||
|
realm.write(function () {
|
||||||
|
if (id == list.items.length) {
|
||||||
|
list.items.push({text: text});
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
var todoItem = list.items[id];
|
||||||
|
todoItem.text = text;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
// should not be needed once we have notifications
|
||||||
|
this.props.parent.updateDataSource();
|
||||||
|
this.props.navigator.pop();
|
||||||
|
}
|
||||||
|
|
||||||
this.setState({
|
render() {
|
||||||
dataSource: this.state.dataSource.cloneWithRows(olderThan30),
|
return (
|
||||||
});
|
<View style={{flex:1, justifyContent: 'flex-start'}}>
|
||||||
},
|
<TextInput multiline={true} style={styles.textInput}
|
||||||
});
|
placeholder='Enter Todo' autoFocus={true}
|
||||||
|
onChangeText={(text) => this.setState({text})} value={this.state.text}/>
|
||||||
|
<TouchableHighlight
|
||||||
|
style={styles.button}
|
||||||
|
onPress={this.save.bind(this)}
|
||||||
|
underlayColor='#99d9f4'>
|
||||||
|
<Text style={styles.buttonText}>Save</Text>
|
||||||
|
</TouchableHighlight>
|
||||||
|
</View>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class TodoList extends React.Component {
|
||||||
|
componentWillMount() {
|
||||||
|
this.lists = realm.objects('TodoList');
|
||||||
|
if (this.lists.length < 1) {
|
||||||
|
realm.write(function() {
|
||||||
|
this.list = realm.create('TodoList', ['List', []]);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.list = this.lists[0];
|
||||||
|
}
|
||||||
|
this.menu = this.menu.bind(this);
|
||||||
|
this.delete = this.delete.bind(this);
|
||||||
|
var dataSource = new ListView.DataSource({
|
||||||
|
rowHasChanged: (row1, row2) => row1 !== row2
|
||||||
|
});
|
||||||
|
|
||||||
|
this.updateDataSource(dataSource);
|
||||||
|
}
|
||||||
|
|
||||||
|
updateDataSource(oldDataSource) {
|
||||||
|
if (!oldDataSource) {
|
||||||
|
oldDataSource = this.state.dataSource;
|
||||||
|
}
|
||||||
|
this.setState({dataSource: oldDataSource.cloneWithRows(this.list.items)});
|
||||||
|
}
|
||||||
|
|
||||||
|
menu(todo, todoID) {
|
||||||
|
AlertIOS.alert(
|
||||||
|
todo.text,
|
||||||
|
todoID,
|
||||||
|
[
|
||||||
|
{text: 'Complete', onPress: () => this.delete(todoID)},
|
||||||
|
{text: 'Edit', onPress: () => this.edit(todoID, todo.text)},
|
||||||
|
{text: 'Cancel'}
|
||||||
|
]
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
delete(todoID) {
|
||||||
|
var item = this.list.items[todoID];
|
||||||
|
realm.write(function() {
|
||||||
|
realm.delete(item);
|
||||||
|
})
|
||||||
|
this.updateDataSource();
|
||||||
|
}
|
||||||
|
|
||||||
|
edit(todoId, text) {
|
||||||
|
this.props.navigator.push({
|
||||||
|
title: text,
|
||||||
|
component: Edit,
|
||||||
|
passProps: {list: this.list, todoId: todoId, text: text, parent: this}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<View style={styles.container}>
|
||||||
|
<ListView style={styles.listView} dataSource={this.state.dataSource} renderRow={(rowData, sectionID, rowID) =>
|
||||||
|
<TouchableHighlight style={styles.listItem} onPress={() => this.menu(rowData, rowID)}>
|
||||||
|
<Text>
|
||||||
|
{rowData.text}
|
||||||
|
</Text>
|
||||||
|
</TouchableHighlight>
|
||||||
|
}/>
|
||||||
|
<TouchableHighlight style={styles.button}
|
||||||
|
onPress={() => this.edit(this.list.items.length, "")}>
|
||||||
|
<Text style={styles.buttonText}>+</Text>
|
||||||
|
</TouchableHighlight>
|
||||||
|
<Text style={styles.instructions}>
|
||||||
|
Press Cmd+R to reload,{'\n'}
|
||||||
|
Cmd+Control+Z for dev menu
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class Navigator extends React.Component {
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<NavigatorIOS initialRoute={{component: TodoList, title: 'Todo Items'}} style={{flex:1}}/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
AppRegistry.registerComponent('ReactExample', () => Navigator);
|
||||||
|
|
||||||
var styles = StyleSheet.create({
|
var styles = StyleSheet.create({
|
||||||
container: {
|
container: {
|
||||||
flex: 1,
|
flex: 1,
|
||||||
justifyContent: 'center',
|
justifyContent: 'center',
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
backgroundColor: '#F5FCFF',
|
backgroundColor: '#ffffff',
|
||||||
|
},
|
||||||
|
listItem: {
|
||||||
|
marginTop: 3,
|
||||||
|
padding: 2,
|
||||||
|
backgroundColor:'#ABABAB',
|
||||||
|
alignSelf: 'stretch',
|
||||||
|
flexDirection: 'row',
|
||||||
|
flex:1,
|
||||||
|
},
|
||||||
|
textInput: {
|
||||||
|
alignSelf: 'stretch',
|
||||||
|
borderWidth: 0.5,
|
||||||
|
borderColor: '#0f0f0f',
|
||||||
|
height: 200,
|
||||||
|
fontSize: 13,
|
||||||
|
margin: 6,
|
||||||
|
marginTop: 70,
|
||||||
|
padding: 4,
|
||||||
|
},
|
||||||
|
button: {
|
||||||
|
height: 36,
|
||||||
|
backgroundColor: '#48BBEC',
|
||||||
|
alignSelf: 'stretch',
|
||||||
|
justifyContent: 'center'
|
||||||
|
},
|
||||||
|
buttonText: {
|
||||||
|
alignSelf: 'center',
|
||||||
},
|
},
|
||||||
instructions: {
|
instructions: {
|
||||||
textAlign: 'center',
|
textAlign: 'center',
|
||||||
color: '#333333',
|
color: '#333333',
|
||||||
marginBottom: 5,
|
marginBottom: 5,
|
||||||
},
|
}
|
||||||
listView: {
|
|
||||||
paddingTop: 20,
|
|
||||||
backgroundColor: '#F5FCFF',
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
|
|
||||||
AppRegistry.registerComponent('ReactExample', () => RealmReact);
|
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
|
|
||||||
#include "RJSArray.hpp"
|
#include "RJSArray.hpp"
|
||||||
#include "RJSObject.hpp"
|
#include "RJSObject.hpp"
|
||||||
|
#include "RJSUtil.hpp"
|
||||||
#include "object_accessor.hpp"
|
#include "object_accessor.hpp"
|
||||||
|
|
||||||
using namespace realm;
|
using namespace realm;
|
||||||
|
@ -79,11 +80,29 @@ void ArrayPropertyNames(JSContextRef ctx, JSObjectRef object, JSPropertyNameAccu
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
JSValueRef ArrayPush(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* jsException) {
|
||||||
|
try {
|
||||||
|
ObjectArray *array = RJSGetInternal<ObjectArray *>(thisObject);
|
||||||
|
RJSValidateArgumentCount(argumentCount, 1);
|
||||||
|
array->link_view->add(RJSAccessor::to_object_index(ctx, array->realm, const_cast<JSValueRef &>(arguments[0]), array->object_schema.name, false));
|
||||||
|
}
|
||||||
|
catch (std::exception &exp) {
|
||||||
|
if (jsException) {
|
||||||
|
*jsException = RJSMakeError(ctx, exp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
JSObjectRef RJSArrayCreate(JSContextRef ctx, realm::ObjectArray *array) {
|
JSObjectRef RJSArrayCreate(JSContextRef ctx, realm::ObjectArray *array) {
|
||||||
return RJSWrapObject<ObjectArray *>(ctx, RJSArrayClass(), array);
|
return RJSWrapObject<ObjectArray *>(ctx, RJSArrayClass(), array);
|
||||||
}
|
}
|
||||||
|
|
||||||
JSClassRef RJSArrayClass() {
|
JSClassRef RJSArrayClass() {
|
||||||
static JSClassRef s_objectClass = RJSCreateWrapperClass<Object>("Results", ArrayGetProperty, NULL, NULL, NULL, ArrayPropertyNames);
|
const JSStaticFunction arrayFuncs[] = {
|
||||||
|
{"push", ArrayPush},
|
||||||
|
{NULL, NULL},
|
||||||
|
};
|
||||||
|
static JSClassRef s_objectClass = RJSCreateWrapperClass<Object>("RealmArray", ArrayGetProperty, NULL, arrayFuncs, NULL, ArrayPropertyNames);
|
||||||
return s_objectClass;
|
return s_objectClass;
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,10 +18,13 @@
|
||||||
|
|
||||||
#import "RJSUtil.hpp"
|
#import "RJSUtil.hpp"
|
||||||
#import "shared_realm.hpp"
|
#import "shared_realm.hpp"
|
||||||
|
#import "object_accessor.hpp"
|
||||||
|
|
||||||
namespace realm {
|
namespace realm {
|
||||||
class Object;
|
class Object;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
using RJSAccessor = realm::NativeAccessor<JSValueRef, JSContextRef>;
|
||||||
|
|
||||||
JSClassRef RJSObjectClass();
|
JSClassRef RJSObjectClass();
|
||||||
JSObjectRef RJSObjectCreate(JSContextRef ctx, realm::Object object);
|
JSObjectRef RJSObjectCreate(JSContextRef ctx, realm::Object object);
|
||||||
|
|
|
@ -26,7 +26,6 @@
|
||||||
#import "object_accessor.hpp"
|
#import "object_accessor.hpp"
|
||||||
|
|
||||||
using namespace realm;
|
using namespace realm;
|
||||||
using RJSAccessor = NativeAccessor<JSValueRef, JSContextRef>;
|
|
||||||
|
|
||||||
JSValueRef ObjectGetProperty(JSContextRef ctx, JSObjectRef jsObject, JSStringRef jsPropertyName, JSValueRef* exception) {
|
JSValueRef ObjectGetProperty(JSContextRef ctx, JSObjectRef jsObject, JSStringRef jsPropertyName, JSValueRef* exception) {
|
||||||
Object *obj = RJSGetInternal<Object *>(jsObject);
|
Object *obj = RJSGetInternal<Object *>(jsObject);
|
||||||
|
@ -164,13 +163,13 @@ template<> DateTime RJSAccessor::to_datetime(JSContextRef ctx, JSValueRef &val)
|
||||||
|
|
||||||
extern JSObjectRef RJSDictForPropertyArray(JSContextRef ctx, ObjectSchema &object_schema, JSObjectRef array);
|
extern JSObjectRef RJSDictForPropertyArray(JSContextRef ctx, ObjectSchema &object_schema, JSObjectRef array);
|
||||||
|
|
||||||
template<> size_t RJSAccessor::to_object_index(JSContextRef ctx, SharedRealm &realm, JSValueRef &val, Property &prop, bool try_update) {
|
template<> size_t RJSAccessor::to_object_index(JSContextRef ctx, SharedRealm &realm, JSValueRef &val, std::string &type, bool try_update) {
|
||||||
JSObjectRef object = RJSValidatedValueToObject(ctx, val);
|
JSObjectRef object = RJSValidatedValueToObject(ctx, val);
|
||||||
if (JSValueIsObjectOfClass(ctx, val, RJSObjectClass())) {
|
if (JSValueIsObjectOfClass(ctx, val, RJSObjectClass())) {
|
||||||
return RJSGetInternal<Object *>(object)->row.get_index();
|
return RJSGetInternal<Object *>(object)->row.get_index();
|
||||||
}
|
}
|
||||||
|
|
||||||
ObjectSchema &object_schema = realm->config().schema->at(prop.object_type);
|
ObjectSchema &object_schema = realm->config().schema->at(type);
|
||||||
if (RJSIsValueArray(ctx, object)) {
|
if (RJSIsValueArray(ctx, object)) {
|
||||||
object = RJSDictForPropertyArray(ctx, object_schema, object);
|
object = RJSDictForPropertyArray(ctx, object_schema, object);
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,7 +43,7 @@ namespace realm {
|
||||||
// convert value to persisted object
|
// convert value to persisted object
|
||||||
// for existing objects return the existing row index
|
// for existing objects return the existing row index
|
||||||
// for new/updated objects return the row index
|
// for new/updated objects return the row index
|
||||||
static size_t to_object_index(ContextType ctx, SharedRealm &realm, ValueType &val, Property &prop, bool try_update);
|
static size_t to_object_index(ContextType ctx, SharedRealm &realm, ValueType &val, std::string &type, bool try_update);
|
||||||
|
|
||||||
// array value acessors
|
// array value acessors
|
||||||
static size_t array_size(ContextType ctx, ValueType &val);
|
static size_t array_size(ContextType ctx, ValueType &val);
|
||||||
|
@ -125,7 +125,7 @@ namespace realm {
|
||||||
row.nullify_link(column);
|
row.nullify_link(column);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
row.set_link(column, Accessor::to_object_index(ctx, realm, value, property, try_update));
|
row.set_link(column, Accessor::to_object_index(ctx, realm, value, property.object_type, try_update));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -135,7 +135,7 @@ namespace realm {
|
||||||
size_t count = Accessor::array_size(ctx, value);
|
size_t count = Accessor::array_size(ctx, value);
|
||||||
for (size_t i = 0; i < count; i++) {
|
for (size_t i = 0; i < count; i++) {
|
||||||
ValueType element = Accessor::array_value_at_index(ctx, value, i);
|
ValueType element = Accessor::array_value_at_index(ctx, value, i);
|
||||||
link_view->add(Accessor::to_object_index(ctx, realm, element, property, try_update));
|
link_view->add(Accessor::to_object_index(ctx, realm, element, property.object_type, try_update));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -104,4 +104,8 @@ var ArrayTests = {
|
||||||
}
|
}
|
||||||
TestCase.assertEqual(2, count);
|
TestCase.assertEqual(2, count);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
testPush: function() {
|
||||||
|
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue