Skip to content

Commit de48f62

Browse files
committed
Add support for AngularJS.
1 parent 048fb7e commit de48f62

File tree

8 files changed

+174
-8
lines changed

8 files changed

+174
-8
lines changed

README.md

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -144,15 +144,18 @@ Currently, the store does not handle `links` and `meta` attributes.
144144

145145
### AngularJS
146146

147-
In order to use jsonapi-datastore inside an AngularJS project, simply require the plugin in your `index.html` and then make a factory:
147+
jsonapi-datastore is bundled with an AngularJs wrapper. Just include `ng-jsonapi-datastore.js` in your `index.html` and require the module `beauby.jsonApiDataStore` in your application.
148+
You can then use the `JsonApiDataStore` factory, which is essentially an instance of `JsonApiDataStore`, as follows:
149+
148150
```javascript
149151
angular
150152
.module('myApp')
151-
.factory('JsonApiDataStore', function() {
152-
return new JsonApiDataStore();
153+
.controller('myController', function(JsonApiDataStore) {
154+
var article = JsonApiDataStore.find('article', 1337);
153155
});
154156
```
155157

158+
156159
## Contributing
157160

158161
All pull-requests welcome!

dist/ng-jsonapi-datastore.js

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
angular
2+
.module('beauby.jsonApiDataStore', [])
3+
.factory('JsonApiDataStore', function() {
4+
function JsonApiDataStoreModel(type, id) {
5+
this.id = id;
6+
this._type = type;
7+
this._attributes = [];
8+
this._relationships = [];
9+
}
10+
11+
JsonApiDataStoreModel.prototype.serialize = function(opts) {
12+
var self = this,
13+
res,
14+
key;
15+
16+
opts || (opts = {});
17+
opts.attributes || (opts.attributes = this._attributes);
18+
opts.relationships || (opts.relationships = this._relationships);
19+
20+
res = {
21+
data: {
22+
type: this._type,
23+
id: this.id
24+
}
25+
};
26+
27+
if (opts.attributes.length !== 0) res.data.attributes = {};
28+
if (opts.relationships.length !== 0) res.data.relationships = {};
29+
30+
opts.attributes.forEach(function(key) {
31+
res.data.attributes[key] = self[key];
32+
});
33+
34+
opts.relationships.forEach(function(key) {
35+
function relationshipIdentifier(model) {
36+
return {
37+
type: model._type,
38+
id: model.id
39+
};
40+
}
41+
if (self[key].constructor === Array) {
42+
res.data.relationships[key] = {
43+
data: self[key].map(relationshipIdentifier)
44+
};
45+
} else {
46+
res.data.relationships[key] = {
47+
data: relationshipIdentifier(self[key])
48+
};
49+
}
50+
});
51+
52+
return res;
53+
};
54+
55+
function JsonApiDataStore() {
56+
this.graph = {};
57+
}
58+
59+
JsonApiDataStore.prototype.reset = function() {
60+
this.graph = {};
61+
};
62+
63+
JsonApiDataStore.prototype.find = function(type, id) {
64+
if (!this.graph[type] || !this.graph[type][id]) return null;
65+
return this.graph[type][id];
66+
};
67+
68+
JsonApiDataStore.prototype.destroy = function(model) {
69+
delete this.graph[model._type][model.id];
70+
};
71+
72+
JsonApiDataStore.prototype.initModel = function(type, id) {
73+
this.graph[type] || (this.graph[type] = {});
74+
this.graph[type][id] || (this.graph[type][id] = new JsonApiDataStoreModel(type, id));
75+
76+
return this.graph[type][id];
77+
};
78+
79+
JsonApiDataStore.prototype.syncRecord = function(rec) {
80+
var self = this,
81+
model = this.initModel(rec.type, rec.id),
82+
key;
83+
84+
function findOrInit(resource) {
85+
if (!self.find(resource.type, resource.id)) {
86+
var placeHolderModel = self.initModel(resource.type, resource.id);
87+
placeHolderModel._placeHolder = true;
88+
}
89+
return self.graph[resource.type][resource.id];
90+
}
91+
92+
delete model._placeHolder;
93+
94+
for (key in rec.attributes) {
95+
model._attributes.push(key);
96+
model[key] = rec.attributes[key];
97+
}
98+
99+
if (rec.relationships) {
100+
for (key in rec.relationships) {
101+
var rel = rec.relationships[key];
102+
if (rel.data !== undefined) {
103+
model._relationships.push(key);
104+
if (rel.data === null) {
105+
model[key] = null;
106+
} else if (rel.data.constructor === Array) {
107+
model[key] = rel.data.map(findOrInit);
108+
} else {
109+
model[key] = findOrInit(rel.data);
110+
}
111+
}
112+
if (rel.links) {
113+
console.log("Warning: Links not implemented yet.");
114+
}
115+
}
116+
}
117+
118+
return model;
119+
};
120+
121+
JsonApiDataStore.prototype.sync = function(data) {
122+
var self = this;
123+
124+
function sync(data) {
125+
if (!data) return null;
126+
if (data.constructor === Array) {
127+
return data.map(self.syncRecord.bind(self));
128+
} else {
129+
return self.syncRecord(data);
130+
}
131+
};
132+
sync(data.included);
133+
return sync(data.data);
134+
};
135+
136+
137+
return new JsonApiDataStore();
138+
});

dist/ng-jsonapi-datastore.min.js

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

gulpfile.js

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,14 @@ var gulp = require('gulp'),
22
concat = require('gulp-concat'),
33
rename = require('gulp-rename'),
44
uglify = require('gulp-uglify'),
5-
mocha = require('gulp-mocha');
5+
mocha = require('gulp-mocha'),
6+
wrap = require('gulp-wrap'),
7+
beautify = require('gulp-jsbeautify');
68

7-
var SRC = 'src/*.js',
9+
var SRC = 'src/jsonapi-datastore/*.js',
810
DEST = 'dist/';
911

10-
gulp.task('build', function(done) {
12+
gulp.task('build', function() {
1113
return gulp.src(SRC)
1214
.pipe(concat('jsonapi-datastore.js'))
1315
.pipe(gulp.dest(DEST))
@@ -16,9 +18,20 @@ gulp.task('build', function(done) {
1618
.pipe(gulp.dest(DEST));
1719
});
1820

21+
gulp.task('build-angular', ['build'], function() {
22+
return gulp.src('dist/jsonapi-datastore.js')
23+
.pipe(concat('ng-jsonapi-datastore.js'))
24+
.pipe(wrap({ src: 'src/angular-wrapper.js' }))
25+
.pipe(beautify({ indent_size: 2 }))
26+
.pipe(gulp.dest(DEST))
27+
.pipe(uglify())
28+
.pipe(rename({ extname: '.min.js' }))
29+
.pipe(gulp.dest(DEST));
30+
});
31+
1932
gulp.task('test', ['build'], function() {
2033
gulp.src('test/*.js')
2134
.pipe(mocha());
2235
});
2336

24-
gulp.task('default', ['build']);
37+
gulp.task('default', ['build', 'build-angular']);

package.json

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@
33
"version": "0.1.2-alpha",
44
"description": "JavaScript client-side JSON API data handling made easy.",
55
"main": "dist/jsonapi-datastore.js",
6-
"files": [ "dist/" ],
6+
"files": [
7+
"dist/"
8+
],
79
"directories": {
810
"test": "test"
911
},
@@ -31,9 +33,11 @@
3133
"chai": "^3.2.0",
3234
"gulp": "^3.9.0",
3335
"gulp-concat": "^2.6.0",
36+
"gulp-jsbeautify": "^0.1.1",
3437
"gulp-mocha": "^2.1.3",
3538
"gulp-rename": "^1.2.2",
3639
"gulp-uglify": "^1.2.0",
40+
"gulp-wrap": "^0.11.0",
3741
"mocha": "^2.2.5"
3842
}
3943
}

src/angular-wrapper.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
angular
2+
.module('beauby.jsonApiDataStore', [])
3+
.factory('JsonApiDataStore', function() {
4+
<%= contents %>
5+
6+
return new JsonApiDataStore();
7+
});
File renamed without changes.
File renamed without changes.

0 commit comments

Comments
 (0)