-
Notifications
You must be signed in to change notification settings - Fork 5
Home
Frui.ts is a frontend framework using MVVM design pattern for clean separation of concerns and long-term maintainability.
Frui.ts is family of indenpendent packages witch toghether creates full MVVM framework. Packages could be also used alone, or some parts could be replaced by another library of your choise.
It allows ViewModel-first approach, which enables automated testing of complex workflows on the ViewModel level with no need to simulate actual user interaction with the UI.
This framework is designed to support both small and large applications with SOLID codebase. It is built on top of the React library, using MobX and written in the modern TypeScript language.
Because you can write this:
model.ts
- define your model or entities, define validation rules
interface ICustomer {
id: number;
firstName: string;
lastName: string;
categoryId: number;
}
const CustomerValidationRules = {
firstName: { maxLength: 35 },
lastName: { required: true, maxLength: 35 },
categoryId: { required: true },
};
viewModel.ts
- write only the code that actually makes sense
class CustomerViewModel {
categories = [
{ id: 1, name: "Premium" },
{ id: 2, name: "Standard" },
];
@observable customer: ICustomer;
constructor(private customerId, private repository: ICustomersRepository) {}
async onInitialize() {
this.customer = await this.repository.loadCustomer(this.customerId);
attachAutomaticValidator(this.customer, CustomerValidationRules);
}
get canSave() {
return isValid(this.customer);
}
@action.bound
async save() {
await this.repository.updateCustomer(this.customerId, this.customer);
}
}
view.tsx
- declare how the VM should be presented
const customerView: ViewComponent<CustomerViewModel> = observer(({ vm }) => (
<form onSubmit={preventDefault(vm.submit)}>
{/* Note the two-way binding here, autocomplete works for 'target' and 'property' properties */}
<Input target={vm.customer} property="firstName" label="First name" />
<Input target={vm.customer} property="lastName" label="Last name" />
<Select
target={vm.customer}
property="categoryId"
label="Category"
items={vm.categories}
keyProperty="id"
textProperty="name"
mode="key"
/>
{/* The button will be enabled/disabled as the input values change */}
<Button type="submit" disabled={!vm.canSave}>
Save
</Button>
</form>
));
registerView(customerView, CustomerViewModel);