I am using jaydata 1.5.1 with odata 4 and ASP.Net WebAPI OData 4. Unfortunately almost all of the examples on the jaydata website are for older versions of jaydata itself or odata protocols < 4.0. I couldn't find any suitable example that covers jaydata > 1.5 + odata 4 + angularjs which makes me at least feel that this project (jaydata) is kind of dying.
I managed to init the jaydata service and to request data. But as soon as I am trying to manipulate data (adding, editing, saving) I am getting errors I can not resolve due to a lack of documentation. Please find here the code I have so far:
index.html
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Cache-Control" content="no-store" />
<meta charset="utf-8" />
<link href="Content/bootstrap.min.css" rel="stylesheet" />
<link href="css/font-awesome.min.css" rel="stylesheet" />
<script src="Scripts/jquery-1.10.2.min.js"></script>
<script src="Scripts/odatajs-4.0.0/odatajs-4.0.0.min.js"></script>
<script src="Scripts/angular.min.js"></script>
<script src="Scripts/jaydata/jaydata.js"></script>
<script src="Scripts/jaydata/jaydatamodules/angular.min.js"></script>
<!--<script src="Scripts/jaydata/jaydataproviders/oDataProvider.min.js"></script>-->
<!--<script src="app/model.js"></script>-->
<script src="app/app.js"></script>
</head>
<body data-ng-app="app">
<div ng-controller="ItemController">
<ul>
<li ng-repeat="item in Items">
<input id="checkSlave" type="checkbox" ng-model="item .IstAktiv">
{{item .Vorname}} {{item .Name}} ({{item .Klinik}} - {{item .Abteilung}} : {{item .Station}})
</li>
</ul>
<button ng-click="newItem()">add new</button>
<p>
<form ng-if="selectedItem">
<fieldset style="width: 300px; background-color: #0094ff;">
<legend>{{selectedItem.Name}}</legend>
<br />
<label>
<table class="table table-striped table-bordered table-condensed">
<thead>
<tr>
<td class="text-center">Aktiv</td>
<td class="text-center">Vorname</td>
<td class="text-center">Name</td>
<td class="text-center">Klinik</td>
<td class="text-center">Abteilung</td>
<td class="text-center">Station</td>
</tr>
</thead>
<tbody>
<tr>
<td class="text-center"><input id="checkSlave" type="checkbox" ng-model="selectedItem.IstAktiv"></td>
<td class="text-center"><input ng-model="selectedItem.Vorname" size="20" /></td>
<td class="text-center"><input ng-model="selectedItem.Name" size="20" /></td>
<td class="text-center"><input ng-model="selectedItem.Klinik" size="20" /></td>
<td class="text-center"><input ng-model="selectedItem.Abteilung" size="20" /></td>
<td class="text-center"><input ng-model="selectedItem.Station" size="20" /></td>
</tr>
</tbody>
</table>
</label>
<button ng-click="save()">Save</button>
<button ng-click="remove()">Remove</button>
</fieldset>
</form>
</p>
</div>
</body>
</html>
app.js:
var app = angular.module('app', ['jaydata']);
app.controller('ItemController', ['$scope', '$data', function ($scope, $data, $q) {
$scope.Items = [];
$scope.selectedItem = null;
$data.initService('http://odata/test/JaydataTest/')
.then(function (context) {
$scope.context = context;
context
.Items
//.map(function (p) { return p.Name })
//.select("{ CategoryObject: it.Category, Name: it.Name }")
//.filter(function (item) { item.Name.startsWith('Kim');})
// .filter(function (product) { return product.Id > idParam }, { idParam: 2 })
//.find(2)
//.orderBy(function (item) {item.Klinik})
.toArray()
.then(function (result) {
$scope.Items = result;
$scope.$apply();
})
})
.catch(function (error) {
alert(error);
});
$scope.save = function () {
if ($scope.selectedItem.ItemId) {
// save existing
$scope.context.Items.attach($scope.selectedItem, true);
$scope.selectedItem.entityState = $data.EntityState.Modified;
}
else {
// save new
$scope.context.Items.add($scope.selectedItem, true);
}
$scope.saveChanges();
};
$scope.saveChanges = function () {
$scope.context.saveChanges()
.then(function (n) {
$scope.selectedItem = null;
$scope.$apply();
})
.fail(function (error) { console.log(error); });
}
$scope.newItem = function () {
var ctx = $scope.context;
$scope.selectedItem = new ctx.Items.elementType({Name: "new Item"})
};
}])
I get the following errors:
1) when saving, data is saved correctly to the underlying database but I get the follwing console error and the context is not getting updated and the new item doesn't show up only after refreshing the page (angular.js = jaydatamodules/angular.js):
TypeError: n.call(...).then(...).fail is not a function
at Container.a.default.EntityContext.saveChanges (angular.js:266)
at n.$scope.saveChanges (app.js:112)
at n.$scope.save (app.js:91)
at fn (eval at <anonymous> (angular.js:14432), <anonymous>:4:203)
at b (angular.js:15485)
at e (angular.js:25018)
at n.$eval (angular.js:17229)
at n.$apply (angular.js:17329)
at HTMLButtonElement.<anonymous> (angular.js:25023)
at HTMLButtonElement.x.event.dispatch (jquery-1.10.2.min.js:22)
I have tried different syntaxes (then/fail then/catch success/error callback) but can't get around this error. Any ideas?
2) While saving data works, updating doesn't. I am getting the following error:
PATCH http://odata/test/JaydataTest//Items(21) 400 (Bad Request) @ odatajs-4.0.0.js:4366
Exception {name: "HTTP request failed", message: "The request is invalid.", data: Object} @ jaydata.js:4315
oDataProvider.js:4156 Uncaught (in promise) Exception {name: "HTTP request failed", message: "The request is invalid.", data: Object}
How to solve this error?
ODataController:
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;
using System.Web.ModelBinding;
using System.Web.OData;
using System.Web.OData.Query;
using System.Web.OData.Routing;
using Model;
namespace JaydataTest.Controllers.odata
{
/*
The WebApiConfig class may require additional changes to add a route for this controller. Merge these statements into the Register method of the WebApiConfig class as applicable. Note that OData URLs are case sensitive.
using System.Web.OData.Builder;
using System.Web.OData.Extensions;
using Model;
ODataConventionModelBuilder builder = new ODataConventionModelBuilder();
builder.EntitySet<Item>("Items");
config.MapODataServiceRoute("odata", "odata", builder.GetEdmModel());
*/
public class ItemsController : ODataController
{
private ModelContext db = new ModelContext();
// GET: odata/Items
[EnableQuery]
public IQueryable<Item> GetItems()
{
return db.Items;
}
// GET: odata/Items(5)
[EnableQuery]
public SingleResult<Item> GetItem([FromODataUri] int key)
{
return SingleResult.Create(db.Items.Where(item => item.ItemId == key));
}
// PUT: odata/Items(5)
public IHttpActionResult Put([FromODataUri] int key, Delta<Item> patch)
{
Validate(patch.GetEntity());
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
Item item = db.Items.Find(key);
if (item == null)
{
return NotFound();
}
patch.Put(item);
try
{
db.SaveChanges();
}
catch (DbUpdateConcurrencyException)
{
if (!ItemExists(key))
{
return NotFound();
}
else
{
throw;
}
}
return Updated(item);
}
// POST: odata/Items
public IHttpActionResult Post(Item item)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
db.Items.Add(item);
db.SaveChanges();
return Created(item);
}
// PATCH: odata/Items(5)
[AcceptVerbs("PATCH", "MERGE")]
public IHttpActionResult Patch([FromODataUri] int key, Delta<Item> patch)
{
Validate(patch.GetEntity());
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
Item item = db.Items.Find(key);
if (item == null)
{
return NotFound();
}
patch.Patch(item);
try
{
db.SaveChanges();
}
catch (DbUpdateConcurrencyException)
{
if (!ItemExists(key))
{
return NotFound();
}
else
{
throw;
}
}
return Updated(item);
}
// DELETE: odata/Items(5)
public IHttpActionResult Delete([FromODataUri] int key)
{
Item item = db.Items.Find(key);
if (item == null)
{
return NotFound();
}
db.Items.Remove(item);
db.SaveChanges();
return StatusCode(HttpStatusCode.NoContent);
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
db.Dispose();
}
base.Dispose(disposing);
}
private bool ItemExists(int key)
{
return db.Items.Count(e => e.ItemId == key) > 0;
}
}
}
jaydatamodules/angular.js (excerpt)
var originalSave = $data.Entity.prototype.save;
var originalRemove = $data.Entity.prototype.remove;
var originalSaveChanges = $data.EntityContext.prototype.saveChanges;
$data.EntityContext.prototype.saveChanges = function () {
var _this = this;
var d = $q.defer();
originalSaveChanges.call(_this).then(function (n) {
cache = {};
d.resolve(n);
if (!$rootScope.$$phase) $rootScope.$apply();
}).fail(function (err) {
d.reject(err);
if (!$rootScope.$$phase) $rootScope.$apply();
});
return d.promise;
}
return $data;
}]);
Help is very much appreciated. Thanks in advance
I recommend you to check out the the JayData angular2 quickstart and jaydata odata v4 example repositories. Both use JayData 1.5.5 RC that doesn't need odatajs anymore as it already includes a patched version of it.
You have to include following module:
<script src="Scripts/jaydatamodules/deferred.js"></script>
http://jaydata.org/blog/how-to-work-with-the-jaydata-promise-interfaces
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.