Giter VIP home page Giter VIP logo

angular-resource-sails's Introduction

angular-resource-sails

Sails.js is a realtime MVC framework built for NodeJS. Angular is a front end framework for building client side web applications. One of Angular's features is ngResource, a small service that allows developers to create objects on the client that can be saved and deleted as if they were on the server. It's a fantastic abstraction that eliminates the usual plumping code of making a change on the client, doing an HTTP call, and handling the response. However, it only works with the Angular $http service, which does not operate using socket.io as Sails.js does.

angular-resource-sails bridges this gap by allowing you to create service objects that behave like those from ngResource but do all of their updating through Sails.js socket.io connections. It also sets up the binding necessary for realtime updates to affect the client.

Install

Install 'angular-resource-sails' via either npm or bower and then and the following to your page head:

<script src="/assets/js/dependencies/sails.io.js"></script>
<script src="/node_modules/angular-resource-sails/src/sailsResource.js"></script>

(note that sails.io.js is a dependency you'll need to include before sailsResource, it's in the assets/js/dependencies folder by default)

Then, in your Angular application dependencies include 'sailsResource' as one of them.

angular.module('myApp', ['sailsResource']);

Usage

###Create model instance

var Item = sailsResource('item');
var newItem = new Item();
newItem.data = 'abc';
newItem.$save(); // POST /item (if the item does not have an id)

###Get a listing of model instances

var items = sailsResource('item').query(); // GET /item

###Get a single model instance

var item = sailsResource('item').get({ id: 53 }); // GET /item/53

###Update a model instance

var item = sailsResource('item').get({ id: 53 });
item.data = 'def';
item.$save(); // PUT /item/53 (if the item has an id)

###Delete a model instance

var item = sailsResource('item').get({ id: 53 });
item.$delete(); // DELETE /item/53

###Success and error callbacks Works like ngResource - can optionally provide callbacks

var item = sailsResource('item').get({ id: 'notreal' }, 
  function(response) { // first function is success handler
    // Handle success
  },
  function(response) { // second function is error handler
    // Handle error
  });

Callbacks also available for actions without parameters.

item.$save(
	function(item) {
		// Handle success
	},
	function(error) {
		// Handle error
	});

###Customize actions Default actions are get, query, save, and remove. You can override these or add your own.

var service = sailsResource('item',
	{
		// create a custom PUT
		'update' { method: 'PUT' }, // Resources will have $update function
		// attach a transformResponse function
		// overrides default query function
		'query': { method: 'GET', isArray: true, function transformResponse(response) {
			// runs after response returns
			return someCustomLogicToRun(response);
		}},
		// attach a transformRequest function
		// overrides default $save function
		'save': { method: 'POST', function transformRequest(request) {
			// runs before request is made
			return JSON.stringify(someCustomLogicToRun(request));
		}}
	}
};

###Options We've included a few useful options you can enable on any sailsResource.

var service = sailsResource('item', {}, {
		verbose: true, // sailsResource will log messages to console
		prefix: 'myapi', // apply a prefix to all routes
		socket: socketInstance // provide your own socket instance,
		origin: 'http://notlocalhost.com' // change the socket origin
	}
};

You can also change these globally by editing the provider's configuration.

angular.module('myapp').config(function (sailsResourceProvider) {
	sailsResourceProvider.configuration = {
		prefix = 'api',
		verbose: true
	};
});

Realtime updates

All angular-resource-sails instances will be subscribed to socket.io updates. If the client receives a create, update, or delete message from the server every instance already created will automatically update as needed.

Additionally, angular-resource-sails will $broadcast a $sailsResourceCreated, $sailsResourceUpdated, and $sailsResourceDestroyed messages when those socket messages are received. You can respond in a customized way by subscribing to those events.

$rootScope.$on('$sailsResourceUpdated', function(event, message) {
	if(message.model == 'user') {
		// some logic for user update messages
	}
});

You can also subscribe to events on collections inside models. The events names are :

  • $sailsResourceAddedTo, when an element has been added in a collection
  • $sailsResourceRemovedFrom when an element has been removed from a collection

Development

  1. bower install

Run Tests

  1. Open SpecRunner.html

angular-resource-sails's People

Contributors

anotherpit avatar dbkaplun avatar dzcpy avatar guillaumeleclerc avatar jasonmore avatar rhettl avatar sean-nicholas avatar xjpro avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

angular-resource-sails's Issues

Unable to create a non static action using GET

Hello,

I have a model User who have notifications. I created a User resource. The correct request to retrieve notifications using sails is : /user/:id/notifications. This is a GET request. I was expecting to do something like this :

var User = sailsResource("user", ....);
var me = User.get({id : "me"});
var notifications = me.$notifications();

But because the notification is a GET request (see) I have to do this (which I think is not the optimal way) :

var User = sailsResource("user", ....);
var me = User.get({id : "me"});
var id = me.id;
var notifications = User.$notifications({id : id});

Do you think we could/should add an option (called static for example) instead of relying on the HTTP method ?

Thank you again for your very useful project !

Errors not handled properly (error callback not called)

Error callback never gets fired, even if the resource is pointing to a non existing endpoint, even though the server responds with 404 codes (seen in WebSocket communication).

Steps to reproduce:

  • create a sailsResource('for non existing endpoint');
  • query() for data -> empty result is returned, success handler is called, which isn't the expected behavior
  • Or just use the sample app and change the "Simples" identifier to something else (in HomeController.js)

Can we do something about it? Thanks in advance

How to submit a DateTime attribute?

Thank you for such a great resource wrapper. It saves time on manually handling socket events.

What is the proper way to submit a Date field? I'm using moment, but native JS Date object is fine.

Thanks in advance,
Pavel.

Model instance does not receive id on create

I created a new model instance as described in the documentation. When i call $save and pass a success callback there is no id, createdAt or updatedAt in the response object:

newItem.$save(function(response) {
    // response has no id, createdAt or updatedAt
});

I tracked this down to https://github.com/angular-resource-sails/angular-resource-sails/blob/master/src/sailsResource.js#L334
handleResponse expects a JWR Object with body attribute but it gets directly passed the body attribute. I think a simple fix is to change

socket[method](url, data, function (response) {

to

socket[method](url, data, function (resData, response) {

Like it is done here https://github.com/angular-resource-sails/angular-resource-sails/blob/master/src/sailsResource.js#L288 and here https://github.com/angular-resource-sails/angular-resource-sails/blob/master/src/sailsResource.js#L369

What do you think?

Error: $rootScope:inprog Action Already In Progress

Hello,

I'm facing this error randomly on firefox :

Error: [$rootScope:inprog] http://errors.angularjs.org/1.4.3/$rootScope/inprog?p0=%24digest J/<@http://localhost:1337/js/dependencies/angular.min.js:6:416 r@http://localhost:1337/js/dependencies/angular.min.js:127:187 jf/this.$get</n.prototype.$apply@http://localhost:1337/js/dependencies/angular.min.js:135:200 handleResponse@http://localhost:1337/js/dependencies/sailsResource.js:222:5 retrieveResource/<@http://localhost:1337/js/dependencies/sailsResource.js:294:6 serverResponded@http://localhost:1337/js/dependencies/sails.io.js:282:11 [5]</Socket.prototype.onack@http://localhost:1337/js/dependencies/sails.io.js:3:11417 [5]</Socket.prototype.onpacket@http://localhost:1337/js/dependencies/sails.io.js:3:10590 [7]</module.exports/<@http://localhost:1337/js/dependencies/sails.io.js:3:13699

I think this is because the code call $rootScope.$apply without checking if angular js is in digest phase.

According to this SO post. The library should call $timeout.

I was working on a pull requests that replace $apply calls by $timeout ones but the tests are failing and I don't get why.

Maybe someone has an idea.

Thank you very muck

Error: $rootScope:inprog when trying to use it with janpantel/angular-sails

What I'm doing:

angular.config(function config ($sailsProvider, sailsResourceProvider) {
// ...
  $sailsProvider.urlPrefix = '/api'
  sailsResourceProvider.configuration = {
    verbose: true
  }
// ...
})
// ...
export class ScenarioListController {
  constructor ($sails, sailsResource) {
    `ngInject`

    const Scenario = sailsResource('scenarios', {}, {
      socket: $sails // important! passing $sails (SailsSocket) instance as 'socket' option
    })
    this.scenarios = Scenario.query()
  }
// ...
}
// ...
<md-list-item ng-repeat="scenario in ctrl.scenarios">
  {{ scenario.name }}
  <!-- ... -->
</md-list-item>

What I'm getting every time I open ScenarioListController route (error repeats several times):

Error: [$rootScope:inprog] $digest already in progress
http://errors.angularjs.org/1.4.9/$rootScope/inprog?p0=%24digest
    at angular.js:68
    at beginPhase (angular.js:16608)
    at Scope.$apply (angular.js:16349)
    at SailsSocket.<anonymous> (sailsResource.js:93)
    at Scope.$eval (angular.js:16251)
    at Scope.$digest (angular.js:16069)
    at Scope.$apply (angular.js:16359)
    at done (angular.js:10791)
    at completeRequest (angular.js:10989)
    at XMLHttpRequest.requestLoaded (angular.js:10930)

As a current workaround I'm wrapping sailsResource() calls inside a $timeout:

    $timeout(() => {
      const Scenario = sailsResource('scenarios', {}, { socket: $sails })
      this.scenarios = Scenario.query()
    })

Also I checked that without angular-sails module with same setup everything works fine (without $timeout wrapping).

Cannot read property 'error'

Hi there,

thanks a lot for this really neat piece of software.

I just stumbled over this error:

TypeError: Cannot read property 'error' of undefined at sailsResource.js:212

Which is (in function handleResponse(item, data, action, deferred, delegate)):

if (data.error || data.statusCode > 400 || isString(data)) {

I just changed that to:

if (data && (data.error || data.statusCode > 400 || isString(data))) {

I'm not that deep into this module. I hope this is the correct solution.

don not support query multi ids

such as Model.query({id :hisIds}, success,fail);
When i try to query data by many ids, it will get error. I doubt why you don't support this usage.

Issue after removing origin feature.

Is there other way to specify URL to sails server?
I have several apps using the same Sails API and origin parameter works well. I have rolled back to 1.1.4, but if you have a minute, can you please tell what is reason to remove this feature and is it planned to be in future versions?
And thanks, angular-resource-sails is really great lib.

query() produces rubbish when only an id parameter is supplied

Running .query() with only an id parameter like so

sailsResource('item').query({ id: 1 })

results in the following response:

[{
    "0": "T",
    "1": "e",
    "2": "s",
    "3": "t"
},
{
    "0": "2",
    "1": "0",
    "2": "1",
    "3": "6",
    "4": "-",
    "5": "0",
    "6": "3",
    "7": "-",
    "8": "0",
    "9": "3",
    "10": "T",
    "11": "1",
    "12": "8",
    "13": ":",
    "14": "0",
    "15": "8",
    "16": ":",
    "17": "3",
    "18": "6",
    "19": ".",
    "20": "2",
    "21": "9",
    "22": "1",
    "23": "Z"
},
{
    "0": "2",
    "1": "0",
    "2": "1",
    "3": "6",
    "4": "-",
    "5": "0",
    "6": "3",
    "7": "-",
    "8": "0",
    "9": "5",
    "10": "T",
    "11": "0",
    "12": "9",
    "13": ":",
    "14": "2",
    "15": "6",
    "16": ":",
    "17": "5",
    "18": "4",
    "19": ".",
    "20": "4",
    "21": "1",
    "22": "3",
    "23": "Z"
}]

query() assumes getting an array and instead it gets an object because I only supplied an id.
I think there are multiple ways to solve this.

  1. The easiest one is to give a warning in the docs and don't change a line of code
  2. Do not create a new Resource in handleRequest. Instead create it based on the response (array or object)
  3. Check before https://github.com/angular-resource-sails/angular-resource-sails/blob/master/src/sailsResource.js#L292 if data is an object then wrap it into an array.
  4. Check in https://github.com/angular-resource-sails/angular-resource-sails/blob/master/src/sailsResource.js#L290 if data is an array, too. And add code to the else statement which creates a new resource if item isn't one.

3 and 4 are kind of the same but in 3 the users gets an array returned and in 4 an object. So the question is: If the user calls query() does she expects always an array or is returning an single object okay, too?

query() results not updated after backend modification.

If I make a query() call, I am returned an array of objects.

If at a later point these objects are modified on my backend, I get a $sailsResourceUpdated message but the resources them selves are not modified on the frontend.

Errors are not catched

Error callback are never called even if there was an error. (Using sails.js v0.11).

I dug into the code and according to the sails.js documentation the callback need to take 2 arguments :

  • the body
  • the jwr

In the library at the moment only the first argument is captured and given to handleResponse. This way the function cannot access the statusCode and potential errors because they are not in the body.

There might be several solution to this problem. I implemented one in a pull request.

Best,

Guillaume Leclerc

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.