Angular和Breeze编辑Date对象

时间:2014-11-17 21:48:30

标签: javascript angularjs asp.net-web-api breeze breeze-sharp

我有一个AngularJS应用程序,我想编辑一个由ASP Web API通过BreezeJS公开的Date对象。当我尝试在HTML表单中编辑此字段时,它不起作用。它似乎编辑了对象的一部分,或者根本没有绑定到日期输入类型。

我想知道用BreezeJS编辑HTML表单中的日期字段的最佳方法是什么。我找不到任何有关如何以正确的方式解决这个问题的资源。

我自己的猜测是:

  1. 使用基于原始日期的额外字段使用getter / setter扩展Breeze实体。
  2. 未在WebAPI中使用日期字段,但感觉不对。
  3. 代码

    在我的Angular控制器中,我通过存储库模式从Breeze获取对象:

    datacontext.session.getById(id)
        .then(function (data) {
             return vm.session = data;
    });
    

    之后vm.session充满了Breeze对象,如下所示:

    [{
        "$id":"1",
        "$type":"TestApp.Model.Session, TestApp.Model",
        "Id":3,
        "Name":"Second session",
        "StartDate":"2014-10-12T00:00:00.000",
    }]
    

    现在,在我的HTML表单中,我像这样绑定:

    <input type="date" ng-model="vm.session.startDate" placeholder="Start Date">
    

    它当前将此日期显示为&#34; Sun Oct 12 2014 02:00:00 GMT + 0200(浪漫夏令时)&#34; 如果我使用的类型&#34;文本&#34;而不是&#34; date&#34;在输入字段中。

    ng-model字段的大小写是正确的,因为我用这个来创建camelCase字段:

    breeze.NamingConvention.camelCase.setAsDefault();
    

    所以这很简单......我会尝试尽快制作JSFiddle或者Plunker

1 个答案:

答案 0 :(得分:0)

Breeze将日期属性维护为JavaScript Date对象,只要您说它们在元数据中的含义。

  

Breeze 拥有自己的Date类型。

HTML5 <input type="date" .../>日期选择器尚未获得广泛支持(请参阅here),因此我假设您依赖the Angular directive来帮助您。

该指令旨在绑定到字符串,而不是日期对象。这可能解释了轮子脱落的原因。

  

我非常想说Ng指令 应该比这个 更聪明。它应该执行绑定到Date对象以及日期字符串所需的操作。我只是将其作为一个错误提交。

正如您所发现的那样,HTML输入标记&#34;只是工作&#34;如果类型是&#34; text&#34;。显然,日期显示和数据输入不是您想要的。

我认为理想的解决方案是拥有一个无缝转换日期对象和字符串值的指令。可能可以通过装饰现有的Ng指令本身来完成。要研究的东西;我们总能使用你的帮助;这是开源的: - )。

同时,您可以在自定义Session类型构造函数上创建已定义的属性。

  

参见&#34;自定义构造函数&#34;在documentation。这样的属性会包装startDate属性(startDateAsString?),解析文本并在出路时格式化为字符串。

这是一个生成Date包装器属性的通用函数:

// Example: addDateWrapperProperty(SessionCtor, 'startDate', 'startDateAsString');

function addDateWrapperProperty(ctor, propName, wrapperPropName) {

    Object.defineProperty(ctor.prototype, wrapperPropName, {
        get: function () { return this[propName].toString(); },
        set: function (value) { this[propName] = value; },
        enumerable: true,
        configurable: true
    });
}

使用它来定义您的startDateAsString包装器属性,然后在编辑时绑定到 此属性 (绑定到只读显示的不动产)。

因为您不希望Breeze对此进行序列化,所以在使用Breeze元数据注册该ctor之后将其添加到ctor中,如下所示。

我不确定这会给你提供你正在寻找的行为。我需要看到你的jsFiddle或者plunkr才能确定。但我认为它会成功。请告诉我们!

肯定不会说这是最终的答案。我不确定答案是什么......虽然我正在考虑我所说的指令。

希望这能让你摆脱困境吧。对不起,这是一个PITA。谁知道Ng不会理解Date对象?

实施例

这是从实际的Breeze测试中提取的一个例子:

/////  Test it //////
var OrderCtor = function () { }; // do-nothing custom constructor

// register the ctor FIRST, then add the property
manager.metadataStore.registerEntityTypeCtor('Order', OrderCtor);

addDateWrapperProperty(OrderCtor, 'orderDate', 'orderDateAsString');

// create new order with a test date
var testDate = new Date(2014,0,1,13,30); // 1/1/2014 1:30 pm

var order = em.createEntity('Order', {
    companyName: "test cust",
    orderDate: testDate
});

// confirm can read the date through the wrapper property
expect(order.orderDate.value).to.equal(testDate.value,
    "'order.orderDate' should return " + testDate);
expect(order.orderDateAsString).to.equal(testDate.toString(),
    "'order.orderDateAsString' should return " + testDate.toString());


var testDate2 = new Date();

// update orderDate by way of the wrapper property
order.orderDateAsString = testDate2.toString();

// confirm the update worked
expect(order.orderDate.value).to.equal(testDate2.value,
    "after update, 'order.orderDate' should return " + testDate2);
expect(order.orderDateAsString).to.equal(testDate2.toString(),
    "after update, 'order.orderDateAsString' should return " + testDate2.toString());

// confirm it is not a breeze-tracked property
var propInfo = order.entityType.getProperty('orderDateAsString');
expect(propInfo).to.equal(null, "'Order.orderDateAsString' is not known to metadata ");