Javascriptmvc tutorial-8. Start Using jquerymx-Model

Source: Internet
Author: User
Tags findone

The javascriptmvc model plug-in provides many tools to better organize model data, such as verification, association, and list. However, the more core functions are service encapsulation, type conversion, and events.

 

  Attribute and Observability

The most important thing for the model layer is to obtain and set the attributes of the model, and listen for changes to the Model instance. The observer mode can be used to solve this problem. MVC uses views to monitor model changes.

Javascriptmvc can easily achieve this observability. A good example is paging. there are often several paging controls on a page. One Control provides the buttons on the previous and next pages, and the other control provides the details displayed on the current page (for example: "1-20 items are being displayed"). All controls must have the same data:

  • Offset-index of the first data displayed
  • Limit-display of information per page
  • Count-Total number of information items

We can use $. Model to create the model data:

var paginate = new $.Model({  offset: 0,  limit: 20,  count: 200});

Now the paginate variable can be viewed. It can be passed to paging controls that perform read/write operations on him or monitor its attribute changes. You can use the traditional method or the model. ATTR (name) method to access paginate attributes:

assertEqual( paginate.offset, 0 );assertEqual( paginate.attr('limit') , 20 );

When we click the next page, we need to increase the offset value. We can use model. ATTR (name, value) to change the attribute value. The following code implements paging:

paginate.attr('offset',20); 

When the status of paginate is modified by a control, other controls need to be notified. You can use model. BIND (ATTR, success (EV, newval) to bind the feature attribute changes, and then update the control:

paginate.bind('offset', function(ev, newVal){  $('#details').text( 'Showing items ' + (newVal+1 )+ '-' + this.count )})

You can also bind 'updated. attr' to listen to any attribute changes:

paginate.bind('updated.attr', function(ev, newVal){  $('#details').text( 'Showing items ' + (newVal+1 )+ '-' + this.count )})

The following code is the code of the next-previous plug-in that accepts the paginate data:

$.fn.nextPrev = function(paginate){   this.delegate('.next','click', function(){     var nextOffset = paginate.offset+paginate.limit;     if( nextOffset < paginate.count){       paginate.attr('offset', nextOffset );     }   })   this.delegate('.prev','click', function(){     var nextOffset = paginate.offset-paginate.limit;     if( 0 < paginate.offset ){       paginate.attr('offset', Math.max(0, nextOffset) );     }   });   var self = this;   paginate.bind('updated.attr', function(){     var next = self.find('.next'),         prev = self.find('.prev');     if( this.offset == 0 ){       prev.removeClass('enabled');     } else {        prev.removeClass('disabled');     }     if( this.offset > this.count - this.limit ){       next.removeClass('enabled');     } else {        next.removeClass('disabled');     }   })};

This plug-in also has some problems. First, if the control is removed from the page, it cannot be unbound from paginate. We will discuss it in the Controller Chapter. Second, there is a logic to determine the offset to prevent it from being a negative number or exceeding the maximum value. This logic should be placed in the model. We need to add other judgments to limit and offset. We need to create a pagination class.

 

  Extended Model

  The model of javascriptmvc inherits from $. class. We create a model class, which is implemented by inheriting $. Model (name, [static,] prototype:

$.Model('Paginate',{  staticProperty: 'foo'},{  prototypeProperty: 'bar'})

There are many ways to make the paginate model more useful. You can first add the setter method to limit the values of offset and count.

 

  Setters

The setter method is the prototype method of the model. It is named setname and has three parameters: Val (passed to the model. ATTR (name, Val), success, and error callback functions. Generally, the method returns the value to be set to the model instance, or executes the error method when an exception occurs. When an asynchronous setter is executed, the success method is executed. The setcount and setoffset instance methods are added in the following example, and the attribute is set to a negative number.

$.Model('Paginate',{  setCount : function(newCount, success, error){    return newCount < 0 ? 0 : newCount;  },  setOffset : function(newOffset, success, error){    return newOffset < 0 ? 0 : Math.min(newOffset, !isNaN(this.count - 1) ? this.count : Infinity )  }})

Currently, the nextprev plug-in uses the following method to set the offset value:

this.delegate('.next','click', function(){  paginate.attr('offset', paginate.offset+paginate.limit);})this.delegate('.prev','click', function(){    paginate.attr('offset', paginate.offset-paginate.limit );});

 

  Default Value

We can set staticThe defaults attribute isThe default value is set for the paginate instance. When a new instance is created, if no other value is set, the default value is used for the instance.

$.Model('Paginate',{  defaults : {    count: Infinity,    offset: 0,    limit: 100  }},{  setCount : function(newCount, success, error){ ... },  setOffset : function(newOffset, success, error){ ... }})var paginate = new Paginate({count: 500});assertEqual(paginate.limit, 100);assertEqual(paginate.count, 500);

Now paginate is very stylish, but it will become better to add a helper method.

 

  Auxiliary Methods

A prototype method is used to obtain or set useful data on an instance. In the following example, paginate contains the next and Prev methods to navigate to different pages. He also provides cannext and canprev methods to determine whether pages can be turned over.

$.Model('Paginate',{  defaults : {    count: Infinity,    offset: 0,    limit: 100  }},{  setCount : function( newCount ){    return Math.max(0, newCount  );  },  setOffset : function( newOffset ){    return Math.max( 0 , Math.min(newOffset, this.count ) )  },  next : function(){    this.attr('offset', this.offset+this.limit);  },  prev : function(){    this.attr('offset', this.offset - this.limit )  },  canNext : function(){    return this.offset > this.count - this.limit  },  canPrev : function(){    return this.offset > 0  }})

Now our jquery plug-ins are becoming more and more stylish.

$.fn.nextPrev = function(paginate){   this.delegate('.next','click', function(){     paginate.attr('offset', paginate.offset+paginate.limit);   })   this.delegate('.prev','click', function(){     paginate.attr('offset', paginate.offset-paginate.limit );   });   var self = this;   paginate.bind('updated.attr', function(){     self.find('.prev')[paginate.canPrev() ? 'addClass' : 'removeClass']('enabled')     self.find('.next')[paginate.canNext() ? 'addClass' : 'removeClass']('enabled');   })};

 

  Service Encapsulation

We have seen how useful $. model is for modeling Client states, but for most programs, data is stored on the server rather than on the client. The client needs data on the CREATE, retrieve, update, and delete (crud) servers. Maintaining client and server data is tricky, and $. model can solve this problem well. $. Model is quite flexible. It can process any service type and data type. Here we only introduce declarative state transfer (rest) and JSON.

The rest service uses URLs and HTTP transmission protocols post, get, put, and delete to create, retrieve, update, and delete data respectively. For example, a job service that allows you to create, retrieve, update, and delete tasks looks like this:

Action Verb) URL Body Response
Create a task Post /Tasks Name = do the dishes
{  "id"       : 2,  "name"     : "do the dishes",  "acl"      : "rw" ,  "createdAt": 1303173531164 // April 18 2011}
Get a task Get /Task/2  
{  "id"       : 2,  "name"     : "do the dishes",  "acl"      : "rw" ,  "createdAt": 1303173531164 // April 18 2011}
Get tasks Get /Tasks  
[{  "id"       : 1,  "name"     : "take out trash",  "acl"      : "r",  "createdAt": 1303000731164 // April 16 2011},{  "id"       : 2,  "name"     : "do the dishes",  "acl"      : "rw" ,  "createdAt": 1303173531164 // April 18 2011}]
Update a task Put /Task/2 Name = take out recycling
{  "id"       : 2,  "name"     : "take out recycling",  "acl"      : "rw" ,  "createdAt": 1303173531164 // April 18 2011}
Delete a task Delete /Task/2  
{}
 

 

The following code connects to the server and allows us to create, retrieve, update, and delete tasks on the server.

$.Model("Task",{  create  : "POST /tasks.json",  findOne : "GET /tasks/{id}.json",  findAll : "GET /tasks.json",  update  : "PUT /tasks/{id}.json",  destroy : "DELETE /tasks/{id}.json"},{ });

The following code shows how to use a task to perform a crud task.

Action Code Description
Create a task
new Task({ name: 'do the dishes'})  .save(     success( task, data ),     error( jqXHR)   ) -> taskDeferred

Create a model instance on the server, first usenew Model(attributes). Then executesave().

In this example, we do not use the task attribute to create a request to save data. We provide two parameters for save:

  • success-If the execution succeeds, the task instance and data are obtained from the server.
  • error-Execution in case of an exception.

Save returns a latency for task creation.

Get a task
Task.findOne(params,   success( task ),   error( jqXHR) ) -> taskDeferred
Obtain a single instance from the server and provide three parameters:

  • params-Data transmitted to the server, for example:{id: 2}.
  • success-If the execution succeeds, the task instance and data are obtained from the server.
  • error-Execution in case of an exception.

Findone returns a delay to solve the task.

Get tasks
Task.findAll(params,   success( tasks ),   error( jqXHR) ) -> tasksDeferred
The task array returned from the server uses three parameters:

  • params-Data to pass to the server. Typically, it's an empty object ({}) Or filters:{limit: 20, offset: 100}.
  • success-If the execution succeeds, the task instance and data are obtained from the server.
  • error-Execution in case of an exception.

Findone returns the tasks array for resolving the latency.

Update a task
task.attr('name','take out recycling');task.save(   success( task, data ),   error( jqXHR) ) -> taskDeferred

When an update is executed on the server, first modifyattrAnd then executesave()。Save uses the same parameters to return the same latency as the created task.

Destroy a task
task.destroy(   success( task, data ),   error( jqXHR) ) -> taskDeferred

Destroy a task on the slave server with two parameters:

  • success-If the execution succeeds, the task instance and data are obtained from the server.
  • error-Execution in case of an exception.

The destroy return delay is used to destroy a task.

The task model becomes the contract of our service.

 

  Type conversion

In JavaScript programming, we often encounter time conversion difficulties. For example, 1303173531164 represents limit l 18th and 2011. We need to use new date (1303173531164) to solve the problem. Fortunately, $. model provides us with the type conversion function, which can easily solve this problem. We need to define a type attribute and the corresponding conversion function. The type attribute is placed on a static object.In attributes, the conversion function is placed in the static object convert, as follows:

$.Model('Task',{  attributes : {    createdAt : 'date'  },  convert : {    date : function(date){      return typeof date == 'number' ? new Date(date) : date;    }  }},{});

We can use the following method:

Task.findAll({}, function(tasks){  $.each(tasks, function(){    console.log( "Year = "+this.createdAt.fullYear() )  })});

 

  Crud event

When an instance is created, updated, or destroyed, the model publishes an event. You can use model. BIND (event, callback (EV, instance) to listen for created, updated, or destroyed events on the model or its instance. When we want to know whether a task is created and added to the page, or when it is updated, we can use the following code:

Task.bind('created', function(ev, task){  var el = $('<li>').html(todo.name);  el.appendTo($('#todos'));  task.bind('updated', function(){    el.html(this.name)  }).bind('destroyed', function(){    el.remove()  })})

 

Javascriptmvc tutorial directory

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.