static TodoAppState SetVisibility(TodoAppState state, SetVisibility act) { return(new TodoAppState { Todos = state.Todos, Visibility = act.Visibility, DescriptionInput = state.DescriptionInput }); }
static TodoAppState UpdateDescriptionInput(TodoAppState state, UpdateDescriptionInput act) { return(new TodoAppState { Todos = state.Todos, Visibility = state.Visibility, DescriptionInput = act.Description }); }
public static ReduxReducer <TodoAppState> Reducer(TodoAppState initialState) => BuildReducer.For <TodoAppState>() .WhenActionHasType <AddTodo>(AddTodo) .WhenActionHasType <DeleteTodo>(DeleteTodo) .WhenActionHasType <UpdateTodo>(UpdateTodo) .WhenActionHasType <ToggleTodoCompleted>(ToggleTodoCompleted) .WhenActionHasType <SetVisibility>(SetVisibility) .WhenActionHasType <UpdateDescriptionInput>(UpdateDescriptionInput) .WhenStateIsUndefinedOrNull(() => initialState) .WhenActionIsUnknown(state => state) .Build();
static TodoAppState ToggleTodoCompleted(TodoAppState state, ToggleTodoCompleted act) => new TodoAppState { Todos = state.Todos.Select(todo => { if (todo.Id == act.Id) { return(new Todo { Id = todo.Id, Description = todo.Description, IsCompleted = !todo.IsCompleted }); } else { return(todo); } }).ToArray(), Visibility = state.Visibility, DescriptionInput = state.DescriptionInput };
private static TodoAppState AddTodo(TodoAppState state, AddTodo act) { int nextId = 0; if (state.Todos.Any()) { var maxId = state.Todos.Max(_todo => _todo.Id); nextId = maxId + 1; } var todo = new Todo { Id = nextId, Description = state.DescriptionInput, IsCompleted = false }; return(new TodoAppState { Todos = state.Todos.Concat <Todo>(new Todo[] { todo }).ToArray(), Visibility = state.Visibility, DescriptionInput = state.DescriptionInput }); }
static TodoAppState DeleteTodo(TodoAppState state, DeleteTodo act) => new TodoAppState { Todos = state.Todos.Where(todo => todo.Id != act.Id).ToArray(), Visibility = state.Visibility, DescriptionInput = state.DescriptionInput };
public static void Main() { var initialState = new TodoAppState { DescriptionInput = "", Visibility = TodoVisibility.All, Todos = new Todo[] { new Todo { Id = 0, Description = "Have fun with Ractive and Redux", IsCompleted = true }, new Todo { Id = 1, Description = "Make an awesome todo app", IsCompleted = false } } }; var store = Redux.CreateStore(Todos.Reducer(initialState)); Action <TodoVisibility> show = filter => store.Dispatch(new SetVisibility { Visibility = filter }); // events that are attached to button clicks on the template var eventHandlers = new EventHandlers { ToggleTodo = id => store.Dispatch(new ToggleTodoCompleted { Id = id }), DeleteTodo = id => store.Dispatch(new DeleteTodo { Id = id }), AddTodo = () => store.Dispatch(new AddTodo { }), ShowAll = () => show(TodoVisibility.All), ShowComplete = () => show(TodoVisibility.Completed), ShowIncomplete = () => show(TodoVisibility.YetToComplete) }; // functions that can be called in the template to compute smth directly var functions = new TemplateFunctions { Filter = (visibility, todos) => { if (visibility == TodoVisibility.Completed) { return(todos.Where(todo => todo.IsCompleted).ToArray()); } if (visibility == TodoVisibility.YetToComplete) { return(todos.Where(todo => !todo.IsCompleted).ToArray()); } return(todos); } }; var ractive = new Ractive(new RactiveOptions { Element = "#app", Template = "#app-template", Data = JS.Merge(initialState, functions) }); // although two-way binding is available in Ractive, // I will use a vanilla handler to make data-flow one directional ractive.Find("#txtAddTodo").OnTextChanged(input => { store.Dispatch(new UpdateDescriptionInput { Description = input }); }); // attach the events ractive.On(eventHandlers); store.Subscribe(() => { var state = store.GetState(); ractive.Set(JS.Merge(state, functions)); }); }