Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

breezejs: overriding displayname

Tags:

breeze

I'm in the process of customizing validation messages. It's working fine using the messageTemplates property. However it uses %displayName% to render the name of the property and I can't find out how to override this value ? Is there anyway to do that ?

like image 202
Sam Avatar asked May 24 '13 10:05

Sam


3 Answers

I was wanting to do this also but I wanted to use the [DisplayName] attribute from my EF model. I couldn't find anyone that had an example of doing this so after I found a way I thought I would share.

First, I extended the metadata returned from my BreezeController:

[HttpGet]
public string Metadata()
{
    // Extend metadata with extra attributes
    JObject metadata = JObject.Parse(contextProvider.Metadata());
    string nameSpace = metadata["schema"]["namespace"].ToString();
    foreach (var entityType in metadata["schema"]["entityType"])
    {
        string typeName = entityType["name"].ToString();
        Type t = Type.GetType(nameSpace + "." + typeName);
        foreach (var prop in t.GetProperties())
        {
            foreach (var attr in prop.CustomAttributes)
            {
                string name = attr.GetType().Name;
                foreach (var p in entityType["property"])
                {
                    if (prop.Name == p["name"].ToString()) {
                        if (attr.AttributeType.Name == "DisplayNameAttribute") {
                            DisplayNameAttribute a = (DisplayNameAttribute)Attribute.GetCustomAttribute(prop, typeof(DisplayNameAttribute));
                            p["displayName"] = a.DisplayName;
                            break;
                        }
                    }
                }
            }
        }
    }

    return metadata.ToString();
}

Then I added a little javascript after the metadata load to poke the display names from the augmented metadata where Breeze wants to find them.

manager.fetchMetadata().then(function (md) {
    angular.forEach(md.schema.entityType, function (et) {
        var etype = manager.metadataStore.getEntityType(et.name);
        angular.forEach(et.property, function (p) {
            var prop = etype.getProperty(p.name);
            prop.displayName = p.displayName;
        });
    });

    console.log("starting app");
    angular.bootstrap($("#app"), ["app"]);
});

I'm using angular so if you aren't you can ignore the angular stuff and probably get the idea. This seems to work rather nicely. It should be pretty easy to extend this to other model attributes as well like the RegularExpression validation attribute. I'll probably work on that next.

FYI, some of this code is not optimized and could probably be refactored, prettied up a bit but I just got it working and thought I would share. If anyone has any suggestions of a better way let me know. Hopefully Breeze will allow extending the metadata in a more supported way in the future. This does seem like a bit of a hack.

like image 155
jpcoder Avatar answered Nov 27 '22 16:11

jpcoder


This is not YET well documented but you can simply set the 'displayName' property on any dataProperty and this will override the autogenerated display name and will be used for all validation messages for this property. So

 var custType = myEntityManager.metadataStore.getEntityType("Customer");
 var dp = custType.getProperty("companyName");
 dp.displayName = "My custom display name";

Also, please see "Customize the message templates" at the bottom of this page: Breeze Validation

like image 22
Jay Traband Avatar answered Nov 27 '22 16:11

Jay Traband


Following jpcoder request for suggestions, here goes my slightly improved server portion:

JObject metadata = JObject.Parse(contextProvider.Metadata());
string nameSpace = metadata["schema"]["namespace"].ToString();
foreach (var entityType in metadata["schema"]["entityType"])
{
    string typeName = entityType["name"].ToString();
    Type t = Type.GetType(nameSpace + "." + typeName);

    IEnumerable<JToken> metaProps = null;
    if (entityType["property"].Type == JTokenType.Object)
        metaProps = new[] { entityType["property"] };
    else
        metaProps = entityType["property"].AsEnumerable();

    var props = from p in metaProps
                let pname = p["name"].ToString()
                let prop = t.GetProperties().SingleOrDefault(prop => prop.Name == pname)
                where prop != null
                from attr in prop.CustomAttributes
                where attr.AttributeType.Name == "DisplayNameAttribute"
                select new
                {
                    Prop = p,
                    DisplayName = ((DisplayNameAttribute)Attribute.GetCustomAttribute(prop, typeof(DisplayNameAttribute))).DisplayName
                };
    foreach (var p in props)
        p.Prop["displayName"] = p.DisplayName;
}
like image 22
vcastro Avatar answered Nov 27 '22 16:11

vcastro