Trying to grasp Kotlin Jetpack Compose and do basic CRUD Operations on a simple TodoList App. Each TodoItem
is a data class and the id's of each will be unique.
Am I approaching this all wrong? I'm stuck at the part trying to get the updated state to render inside ListArea
with a removed TodoItem
or updated TodoItem
. Any help is greatly appreciated, I've been stuck on this for more than two days.
data class TodoItem(
val id: String = "",
val todoName: String = "",
val todoCompleted: Boolean = false
)
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
TodoListACTAppTheme {
// A surface container using the 'background' color from the theme
Surface(
modifier = Modifier.fillMaxSize(),
color = MaterialTheme.colors.background
) {
MainTodoListApp()
}
}
}
}
}
@Composable
fun MainTodoListApp() {
var item1 = TodoItem( id = "aaa", todoName = "Alpha", todoCompleted = false)
var item2 = TodoItem( id = "bbb", todoName = "Bravo", todoCompleted = true)
var item3 = TodoItem( id = "ccc", todoName = "Charlie", todoCompleted = false)
val todosListState = remember {
mutableStateListOf<TodoItem>(item1, item2, item3)
}
fun addNewTodo(todoName: String) {
println("Add Todo $todoName")
val currentTS = System.currentTimeMillis().toString()
var item4 = TodoItem( id = currentTS, todoName = todoName, todoCompleted = false)
todosListState.add(item4) // This works
}
fun completeTodo(todoId: String) {
// STUCK HERE trying to toggle todoCompleted to it's opposite
// Update State with List with toggeled value
println("Complete Todo $todoId")
var newArray = todosListState.map {
it -> if (it.id == todoId)
TodoItem(id = it.id, todoName = it.todoName, todoCompleted = !it.todoCompleted)
else TodoItem(id = it.id, todoName = it.todoName, todoCompleted = it.todoCompleted)
}
//todosListState = newArray THIS DOES NOT WORK
println("New Array ${newArray}")
}
fun deleteTodo(todoId: String) {
// STUCK HERE trying to remove class object from List
// Pass down state with new List with removed objects
println("delete Todo $todoId")
//var newArray = todoItems.filter { p -> p.id != todoId }
println("delete Array ${newArray}")
// THIS does not work
}
Column () {
ListArea(todosListState,
onAddTodo = { x -> addNewTodo(x)},
completeTodo = { x -> completeTodo(x)},
deleteTodo = { x -> deleteTodo(x)},
newTodoName.value,
{newName -> newTodoName.value = newName},)
}
}
@Composable
fun ListArea(
todoList: List<TodoItem>,
onAddTodo: (String) -> Unit,
completeTodo: (String) -> Unit,
deleteTodo: (String) -> Unit,
textFieldValue: String,
textFieldUpdate: (newName: String) -> Unit,
) {
Column() {
Text(text = "List Area of App")
var newNameStateContent = remember { mutableStateOf("") }
Row(
horizontalArrangement = Arrangement.SpaceEvenly,
modifier = Modifier
.fillMaxWidth()) {
TextField(value = newNameStateContent.value,
onValueChange = { newInput -> newNameStateContent.value = newInput }, label = {
Text(text = "New Todo")
}, singleLine = true)
Spacer(Modifier.weight(1.0f))
Button(onClick = {
onAddTodo(newNameStateContent.value)
}) {
Text(text = "Submit")
}
}
todoList.forEach { item ->
TodoItemRow(todo = item,
completeTodo = { x -> completeTodo(x)},
deleteTodo = { x -> deleteTodo(x)})
}
}
}
@Composable
fun TodoItemRow(todo: TodoItem, completeTodo: (String) -> Unit, deleteTodo: (String) -> Unit) {
Column {
Row(modifier = Modifier
.fillMaxWidth()
.padding(10.dp),) {
Button(onClick = { completeTodo(todo.id) } ) {
Text(text = todo.todoName)
}
Spacer(Modifier.weight(1.0f))
Button(onClick = { deleteTodo(todo.id) } ) {
Text(text = "X")
}
}
Divider()
}
}