npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

mvc-pack

v2.0.0

Published

Organize MVC components into packs

Downloads

3

Readme

mvc-pack

The main idea is to help to organize models, views and controllers and to have a single point, where all the components are combined together. This could be treated as a global register of view mapped to a model class. This reduces the interdependency of some simple view in contrast to external views, but it then forcing the need oto manage this maps.

Instalation

npm install mvc-pack

Usage

A recommended rules to follow to create a flexible MVC package:

  • a model must not care about the way how it can be represented, i.e. a model must not know anything about the related views and controllers
  • a model can create another needed models, but view/controller must not create models
  • a model does not create views, but a view can create another needed views
  • a view and a controller are constructing by taking only a reference to a model as an input argument
  • a view and/or a controller listen for a model update events to properly represent the information
  • a view is updating only the part that is changed in the model, i.e. a view must not be fully rerendered, only some part of it must be updated
  • a view is listening user interaction events and updating the model data over the direct dedicated model API or with help of a controller
  • a controller can act as an adapter between the model and the view events, in order to keep raw data in a model and to keep view clean from data processors

Views are providing on demand by an application and the package wrapper is passing a reference to a model as an input argument.

mvcPack(
	SomeModelClass,
	{
		text: vcPack(TextView),
		table: vcPack(TableView, TableController)
	}
);

const model = new SomeModelClass();

console.log(getView(model, 'table') instanceof TableView);   // -> true

It is also possible to register view by providing own custom function for that. The only thing to keep in mind, that that function must return a view:

class CustomView {
	...
}

class CustomController {
	...
}

mvcPack(
	SomeModelClass,
	{
		customView(model) {
			const view = new CustomView(model, 'other arguments');
			const controller = new CustomController(model, 'other arguments');
			view.setController(controller);
			return view;
		}
	}
);

Model

It is recommended to create a base model class in scope of an application, in order to attach an event system to trigger and receive events. For example when some property is changing - update all connected views, or when a model is destructing - properly clean up the views.

class Model {
	constructor() {
		this._eventSystem = new EventTarget();

		this.data = {};
	}

	destruct() {
		this.data = null;
		this.dispatchEvent('destruct');
	}

	setData(data) {
		for (let key in data) {
			this.data[key] = delta[key];
			this.dispatchEvent(`update-${key}`);
		}

		this.dispatchEvent('update');
	}

	dispatchEvent(type) {
		this._eventSystem.dispatchEvent(new CustomEvent(type));
	}

	addEventListener(type, listener) {
		this._eventSystem.addEventListener(type, listener);
	}

	removeEventListener(type, listener) {
		this._eventSystem.removeEventListener(type, listener);
	}
}

View

In context of this package a "View" is a final chain between a model and the information representation. A view can be an HTML representation, so a View class in this context is a class that, for example creates all the needed HTML elements and or combines other Views to display some information.

An example to assotiate only a view with a model:

class TextView {
	...
}

class TableView {
	...
}

mvcPack(
	SomeModelClass,
	{
		text: vcPack(TextView),
		table: vcPack(TableView)
	}
);

It also can work with other classes, that needs more arguments to be constructed or need to do some extra build steps:

class YourView {
	...
}

mvcPack(
	SomeModelClass,
	{
		customView(model) {
			return new YourView(model, 'other', 'arguments');
		}
	}
);

Controller

Sometimes in between the model and view an additional data processing is needed (for example an aggregation, or an adaptation, or formatting, or something else), but the responsibilities for that is not really related to a model or a view. Or an application might require to reuse the same view component but with different data processors. A controller can help with it here. In order to make it work the following conditions must be met:

  • a model must store the data as raw as possible and must not apply any additional processing functions by reading it;
  • a view must contain the only functionality, that are related for the visual representation, i.e. it must contain the smallest amount of data processors.

Under this conditions a controller between them can be easily inserted - a view must use a controller interface to get and display data, or use it to convert into raw format and set into the model..

class TextController {
	...
}

mvcPack(
	SomeModelClass,
	{
		text: vcPack(TextView, TextController)
	}
);
class CustomController {
	...
}

mvcPack(
	SomeModelClass,
	{
		customView(model) {
			const view = new CustomView(model, 'other arguments');
			const controller = new CustomController(model, 'other arguments');
			view.setController(controller);
			return view;
		}
	}
);

Links