Product
Socket Now Supports uv.lock Files
Socket now supports uv.lock files to ensure consistent, secure dependency resolution for Python projects and enhance supply chain security.
Immutable MVVM for React
IMVVM can be loaded as:
IMVVM
is exposed as a global variable <script src="imvvm.min.js"></script>
$ npm install imvvm
$ bower install imvvm
require(['./imvvm.min.js'], function (IMVVM) {
// Do something with IMVVM
});
var PersonModel = IMVVM.createModel({
uuid: function () {
var i, random;
var uuid = '';
for (i = 0; i < 32; i++) {
random = Math.random() * 16 | 0;
if (i === 8 || i === 12 || i === 16 || i === 20) {
uuid += '-';
}
uuid += (i === 12 ? 4 : (i === 16 ? (random & 3 | 8) : random))
.toString(16);
}
return uuid;
},
id: {
get: function(){
return this.state.id ? this.state.id : this.uuid();
}
},
name: {
get: function(){
return this.state.firstName;
},
set: function(newValue){
this.setState({'name': newValue});
}
},
dob: {
get: function(){
return this.state.dob;
},
set: function(newValue){
this.setState({'dob': newValue});
}
},
gender: {
get: function(){
return this.state.gender;
},
set: function(newValue){
this.setState({'gender': newValue});
}
},
});
var PersonsViewModel = IMVVM.createViewModel({
select: function(id){
var nextState = {};
nextState.collection = this.collection.map(function(person){
if(person.id === id){
nextState.selected = this.Person(person);
return nextState.selected;
}
return person;
}.bind(this));
this.setState(nextState);
},
addPerson: function(value){
var nextState = {};
if(value && value.length > 0){
nextState.selected = this.Person({
name: value
});
nextState.collection = this.collection.slice(0);
nextState.collection = nextState.collection.concat(nextState.selected);
this.setState(nextState);
}
},
deletePerson: function(uid){
var nextState = {};
nextState.collection = this.collection.filter(function(person){
return person.id !== uid;
});
nextState.selected = void(0);
if(nextState.collection.length > 0){
if (this.selected.id === uid){
nextState.selected = this.Person(nextState.collection[0]);
} else {
nextState.selected = this.Person(this.selected);
}
}
this.setState(nextState);
},
getInitialState: function(){
var nextState = {};
nextState.collection = DataService.getData().map(function(person, idx){
if (idx === 0){
nextState.selected = this.Person(person);
return nextState.selected;
}
return this.Person(person, false);
}.bind(this));
return nextState;
},
personStateChangedHandler: function(nextState, prevState){
var persons = {};
persons.collection = this.collection.map(function(person){
if(person.id === nextState.id){
persons.selected = this.Person(nextState, person);
return persons.selected;
}
return person;
}.bind(this));
this.setState(persons);
},
Person: function(){
return new PersonModel(this.personStateChangedHandler).apply(this, arguments);
},
collection: {
get: function(){
return this.state.collection;
},
},
selected: {
get: function() {
return this.state.selected;
}
},
});
var DomainModel = IMVVM.createDomainModel({
getInitialState: function(){
return {
online: true
};
},
undo: function(){
this.setState(this.previousState);
},
online: {
get: function(){
return this.state.online;
},
set: function(newValue){
this.setState({'online': newValue });
}
},
getDomainDataContext: function(){
return {
persons: {
viewModel: PersonsViewModel,
dependsOn: [{property: 'online', alias: 'imOnline'}]
}
};
}
});
var ApplicationView = React.createClass({
mixins: [IMVVM.mixin],
render: function(){
return (
<div>
<NavBarView appContext={this.state.applicationDataContext} />
<SideBarView appContext={this.state.applicationDataContext} />
<DetailsView appContext={this.state.applicationDataContext} />
</div>
);
}
});
React.renderComponent(<ApplicationView domainModel={DomainModel}/>, document.getElementById('container'));
FormView example
var FormView = React.createClass({
updateName: function(e){
this.props.appContext.persons.selected.name = e.target.value;
},
updateGender: function(e){
this.props.appContext.persons.selected.gender = e.target.value;
},
updateDOB: function(e){
this.props.appContext.persons.selected.dob = e.target.value;
},
render: function() {
var current = this.props.appContext.persons.selected;
return (
<div key={current.id}>
<form className="form-horizontal" role="form">
<div className="form-group">
<label className="col-md-2 control-label">Name</label>
<div className="col-md-3">
<input className="form-control" type="text" value={current.name}
onChange={this.updateName} />
</div>
</div>
<div className="form-group">
<label className="col-md-2 control-label">Gender</label>
<div className="col-md-3">
<div className="radio">
<label>
<input type="radio" onChange={this.updateGender} value="male"
checked={current.gender === 'male'} />
Male
</label>
</div>
<div className="radio">
<label>
<input type="radio" onChange={this.updateGender} value="female"
checked={current.gender === 'female'} />
Female
</label>
</div>
</div>
</div>
<div className="form-group">
<label className="col-md-2 control-label">Birthday</label>
<div className="col-md-3">
<input className="form-control" type="text"
placeholder="yyyy-mm-dd"
value={current.dob}
onChange={this.updateDOB} />
</div>
</div>
</form>
</div>
);
}
});
##Running the example application
The example application is a good starting place when figuring out how things work. So to get it running, navigate to the ./example
directory and run the following commands.
$ npm install
$ bower install
$ bower install imvvm
$ grunt serve
##API
###Class ####Constructors
#####function createDomainModel(object specification) Creates a DomainModel object.
parameters
specification - see Specification
#####function createViewModel(object specification) Creates a ViewModel object.
parameters
specification - see Specification
#####function createModel(object specification) Creates a Model object.
parameters
specification - see Specification
###Instance ####Functions
#####void setState(object nextState[, function callback]) Transition Data Context to the next state.
parameters
nextState callback
Available in: DomainModel, ViewModel, Model
#####object extend(object currentState[, object... nextState]) Creates a shallow copy of currentState. Adds/replaces properties with properties of subsequent objects.
parameters
currentState nextState
Available in: DomainModel, ViewModel, Model
####Properties
#####state
Available in: DomainModel, ViewModel, Model
#####previousState
Available in: DomainModel
###Specification ####Hooks
#####function getDomainDataContext()
Available in: DomainModel
Optional: false
#####object getInitialState()
Available in: DomainModel, ViewModel
Optional: true
#####object getInitialCalculatedState(object nextState, object previousState)
arguments
nextState
previousState
Available in: DomainModel, ViewModel, Model
Optional: true
#####object getValidState(object nextState, object previousState)
arguments
nextState
previousState
Available in: DomainModel, ViewModel, Model
Optional: true
####Field Descriptor
#####* get() #####void set(* newValue) #####pseudo:boolean #####calculated:boolean
Available in: DomainModel, ViewModel, Model
####DependsOn Properties
Public This will be made available to the View from this Data Context
Private Hidden from View from this Data Context
Available in: ViewModel
####Model State Change Handlers
#####void ModelStateChangeHandler(object nextState,object previousState[, function callback])
arguments
nextState
previousState
callback
personStateChangeHandler: function(nextState, prevState){
var persons = {};
persons.collection = this.collection.map(function(person){
if(person.id === nextState.id){
persons.selected = this.Person(nextState, person);
return persons.selected;
}
return person;
}.bind(this));
this.setState(persons);
}
Available in: ViewModel
####Model Factory Functions
Definition
#####function ModelFactory(){ return new ModelClass(this.ModelStateChangeHandler).apply(this, arguments); }
Usage
#####object ModelFactory([object nextState, object previousState, boolean withContext]) #####object ModelFactory([object nextState, boolean withContext])
Available in: ViewModel
###Mixin ####mixin
mixins: [IMVVM.mixin],
React.renderComponent(, document.getElementById('container'));
this.state.applicationDataContext
Most ECMAScript 5 compliant browsers. IE8 and below are not supported
Entrendipity - Follow @entrendipity
Frank Panetta - Follow @fattenap
##License ###The MIT License (MIT)
Copyright (c) 2014 Entrendipity
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
FAQs
Immutable MVVM for React - Renamed: Please use Astarisx
The npm package imvvm receives a total of 5 weekly downloads. As such, imvvm popularity was classified as not popular.
We found that imvvm demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Product
Socket now supports uv.lock files to ensure consistent, secure dependency resolution for Python projects and enhance supply chain security.
Research
Security News
Socket researchers have discovered multiple malicious npm packages targeting Solana private keys, abusing Gmail to exfiltrate the data and drain Solana wallets.
Security News
PEP 770 proposes adding SBOM support to Python packages to improve transparency and catch hidden non-Python dependencies that security tools often miss.