Breeze and Angular 'ToDo' app does not work with IE 8
Asked Answered
A

3

6

I have downloaded the sample 'Breeze 0.83.5' applications from http://www.breezejs.com/documentation/download

The Angular 'ToDo' sample does not work with IE8.

I have included the following script references above my Breeze script reference.

Any idea why this doesn't work?

Ascribe answered 9/1, 2013 at 15:2 Comment(0)
F
3

Breeze's Angular support makes use of the 'backingStoreAdapter' which in turn depends on the ES5 Javascript 'defineProperty' method being implemented by the browser. This was not implemented in IE8, and unfortunately, cannot be supplemented via the use of a shim.

This is the only adapter that has this limitation, the breeze knockout and backbone adapters, both work with IE8 with the use of ES5 shims.

Sorry!

Fatherinlaw answered 9/1, 2013 at 18:30 Comment(7)
Hi Jay, any idea if it will be corrected in future versions? We need to support IE8 and angular itself has no problems running in IE8. Thx.Muire
We've looked at it but are not quite sure how to implement the internal change notifications in breeze that we need without 'defineProperty'. Angular's watch capability occurs too late for us to use it ( I think). But ... please add this item to the breeze user voice ( and vote for it). Also take a look at breeze's backingStore implementation and if you can come up with a another approach to implementing it, please let me know. This is frustrating, I know, because Angular really does work really well with breeze on modern browsers.Fatherinlaw
Hey Jay... awesome work with Breeze! What a marvelous "piece" of software. Congrats for making it available for US all to use. Regarding IE 8 support: looks like a fix was merged here: github.com/es-shims/es5-shim/issues/5 With this shim fix do you think it would be viable to use Angular & Breeze together on IE 8?Neutral
We are going to follow up on your suggestion, @LenielMacaferi. It seems too good to be true. We'll find out.Veg
@Ward: Great! Let's hope that fix really adds the necessary support.Neutral
@Ward: Is there any place where we can track your investigation, or will you update this question should your investigation proves fruitful?Rosenstein
Pay attention here. I'll update this spot when I have a definitive answer. FWIW, not looking good at the moment. Still have to confirm but the referenced blog post on the shim appears to be wrong about IE8. The __defineGetter__ (like defineProperty) only works for DOM element properties in IE8, not for JS obj properties. That's useless. No way you want Breeze to use the IE8 DOM for its change tracking! I've got one more thing to try. If that fails (LIKELY), we're back to nothing. Yes ... we're disappointed. I did say that it sounds too good to be true ... and so it seems to be.Veg
N
1

It will not work on IE8 in the future versions of Breeze neither.

Todo-Angular runs in modern browsers such as IE9, IE10, and recent Chrome, Safari, Firefox, and WebKit browsers. Breeze does not support AngularJS apps running in older browsers that lack ECMAScript 5 property getters and setters.

Northman answered 1/4, 2013 at 8:42 Comment(2)
Not sure what you mean about not working on future versions. We test right now on the latest Firefox, Chrome and IE. The backingStore adapter works just fine on all three. Do you have a case where it doesn't?Fatherinlaw
Sorry for the ambiguity. What I mean was, it will not work on IE8 even in future versions of Breeze due to defineProperty cannot be shimmed in IE8 as you already said. I'l update my answer accordingly.Falcongentle
P
0

Breeze uses the ViewModel of the hosting MVVM framework. That’s generally a good decision. Additionally, change tracking on entities is a fundamental concept of breeze.js (same for Entity Framework). It’s an easy task to track changes if the MVVM framework uses Observables with real getter and setters (e.g. Knockout). AngularJS on the other hands works with plain JavaScript objects. This makes change tracking difficulty. The only two reliable ways are ES5-properties (simple, but not supported by IE8) or a very deep integration in the $digest cycle. The breeze-team took the first-choice - what a pity for projects that have to support IE8!

Ok, let's analyze the root cause of the problem: change tracking

Do you really need that feature? At least in our project we decided for breeze.js/OData for reading and for a more "restful" approach when it comes to writing. If you don’t need those advanced features, than the following script should solve the issue:

/********************************************************
 * A replacement for the "backingStore" modelLibrary
 * 
 * This is a bare version of the original backingStore,
 * without ANY change tracking - that's why it will work in IE8!
 * (Object.defineProperty not required any more)
 *
 * This adapter is a "drop in" replacement for the "backingStore" adapter in Breeze core.
 * It has the same adapter name so it will silently replace the original "backingStore" adapter
 * when you load this script AFTER the breeze library.
 * WARNING: For obvious reasons a lot of breeze magic will be lost!
 *
 * Author: Johannes Hoppe / haushoppe-its.de
 *
 * Copyright 2014 IdeaBlade, Inc.  All Rights Reserved.  
 * Use, reproduction, distribution, and modification of this code is subject to the terms and 
 * conditions of the IdeaBlade Breeze license, available at http://www.breezejs.com/license
 ******************************************************/

(function (definition, window) {
    if (window.breeze) {
        definition(window.breeze);
    } else if (typeof require === "function" && typeof exports === "object" && typeof module === "object") {
        // CommonJS or Node
        var b = require('breeze');
        definition(b);
    } else if (typeof define === "function" && define["amd"] && !window.breeze) {
        // Requirejs / AMD 
        define(['breeze'], definition);
    } else {
        throw new Error("Can't find breeze");
    }
}(function (breeze) {
    "use strict";

    var core = breeze.core;

    var ctor = function () {
        this.name = "backingStore";
        this.A_BIG_FAT_WARNING = "This is a bare version of the backingStore! Change tracking won't work!";
    };

    var protoFn = ctor.prototype;

    protoFn.initialize = function() {

    };

    protoFn.getTrackablePropertyNames = function (entity) {
        var names = [];
        for (var p in entity) {
            if (p === "entityType") continue;
            if (p === "_$typeName") continue;

            var val = entity[p];
            if (!core.isFunction(val)) {
                names.push(p);
            }
        }
        return names;
    };

    protoFn.initializeEntityPrototype = function (proto) {

        proto.getProperty = function (propertyName) {
            return this[propertyName];
        };

        proto.setProperty = function (propertyName, value) {
            this[propertyName] = value;
            return this;
        };
    };

    // This method is called when an EntityAspect is first created - this will occur as part of the entityType.createEntity call.
    // which can be called either directly or via standard query materialization
    // entity is either an entity or a complexObject
    protoFn.startTracking = function (entity, proto) {

        // assign default values to the entity
        var stype = entity.entityType || entity.complexType;
        stype.getProperties().forEach(function (prop) {

            var propName = prop.name;
            var val = entity[propName];

            if (prop.isDataProperty) {
                if (prop.isComplexProperty) {
                    if (prop.isScalar) {
                        val = prop.dataType._createInstanceCore(entity, prop);
                    } else {
                        val = breeze.makeComplexArray([], entity, prop);
                    }
                } else if (!prop.isScalar) {
                    val = breeze.makePrimitiveArray([], entity, prop);
                } else if (val === undefined) {
                    val = prop.defaultValue;
                }

            } else if (prop.isNavigationProperty) {
                if (val !== undefined) {
                    throw new Error("Cannot assign a navigation property in an entity ctor.: " + prop.Name);
                }
                if (prop.isScalar) {
                    // TODO: change this to nullstob later.
                    val = null;
                } else {
                    val = breeze.makeRelationArray([], entity, prop);
                }
            } else {
                throw new Error("unknown property: " + propName);
            }
            entity[propName] = val;
        });
    };

    breeze.config.registerAdapter("modelLibrary", ctor);
}, this));

Download at: https://gist.github.com/JohannesHoppe/72d7916aeb08897bd256

This is a bare version of the original backingStore, without ANY change tracking - that's why it will work in IE8! (Object.defineProperty not required any more) This adapter is a "drop in" replacement for the "backingStore" adapter in Breeze core. It has the same adapter name so it will silently replace the original "backingStore" adapter when you load the script AFTER the breeze library.

Here is a demo to proof the functionality:
http://jsfiddle.net/Johannes_Hoppe/bcav9hzL/5/

JsFiddle does not support IE8, please use this direct link:
http://jsfiddle.net/Johannes_Hoppe/bcav9hzL/5/embedded/result/

Cheers!

Poohpooh answered 15/10, 2014 at 15:56 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.