This question is locked. New answers and comments are not allowed.
I'm experimenting on how I can restructure my NativeScript app using typescript. The first version of the application used the observable object as it is and everything was working fine. I tried restructuring the code by moving the view model to a different class that wraps around the observable object. The thing is that values are set just fine from the UI but it appears setting the value from code does not change the UI. The idea is to encapsulate everything in the view model and use the generated object like any javascript object without using .get and .set.
MainViewModel.ts
Main.ts
Main.xml
When the add function is called after a button is clicked, the list of items increase but the textbox is not cleared when I set that task property to an empty string.
I did try simply inheriting from observable instead of having a local copy but that caused the application to hang anytime I run it. Very sure I did not implement it well.
What do I do to get the two way binding to work? Am I approaching this wrongly? If so, what is the right way to go around this?
MainViewModel.ts
import observableModule = require("data/observable");import observableArrayModule = require("data/observable-array");import Utils = require("../lib/Utils");export interface ITask { name: string; }export class ViewModel { private observable = new observableModule.Observable(); constructor(json?: any) { this.init(); if (json) for (var key in json) this.observable.set(key, json[key]); } private init() { this.observable.set('task', ''); this.observable.set('tasks', new observableArrayModule.ObservableArray()); } public textFieldId = Utils.uniqueId("ui"); public get task(): string { return this.observable.get('task'); } public set task(value) { this.observable.set('task', value); } public get tasks(): observableArrayModule.ObservableArray<ITask> { return this.observable.get('tasks'); } public set tasks(value) { this.observable.set('tasks', value); } public addTask(task: ITask) { this.tasks.push(task); }}
Main.ts
import viewModule = require("ui/core/view");import textFieldModule = require("ui/text-field");import pageModule = require("ui/page");import frame = require("ui/frame");import model = require("./mainViewModel");var page: pageModule.Page;var vm = new model.ViewModel();export function onPageLoaded(args) { page = args.object; page.bindingContext = vm; if (frame.topmost().android) { frame.topmost().android.actionBar.hide(); }} export function add() { vm.tasks.push({ name: vm.task }); vm.task = ""; var view = viewModule.getViewById<textFieldModule.TextField>(page, vm.textFieldId); view.dismissSoftInput();}Main.xml
<Page loaded="onPageLoaded"> <GridLayout rows="auto,*"> <StackLayout orientation="horizontal" row="0"> <TextField width="200" text="{{task}}" hint="Enter a task" id="{{textFieldId}}"/> <Button text="Add" tap="add"></Button> </StackLayout> <ListView items="{{tasks}}" row="1"> <ListView.itemTemplate> <Label text="{{name}}" /> </ListView.itemTemplate> </ListView> </GridLayout></Page>When the add function is called after a button is clicked, the list of items increase but the textbox is not cleared when I set that task property to an empty string.
I did try simply inheriting from observable instead of having a local copy but that caused the application to hang anytime I run it. Very sure I did not implement it well.
What do I do to get the two way binding to work? Am I approaching this wrongly? If so, what is the right way to go around this?