11

Anyone know if there is any easy way of making a dictionary item editable in experience editor could be using glass or not? I've seen some examples where custom pipelines have been built but wondering if there is any easier way. thanks

  • I wanted to do this and when I looked into it I couldn't find anything anyone has done before so we shelved it for the project I'm currently working on as we didn't have enough time to do it from scratch. I do know someone who says they have done it though so I could give them a nudge and see if they can share what they did. – Adam Seabridge Jan 4 '17 at 17:47
  • 1
    jockstothecore.com/editable-dictionary-items-2 maybe this one is helping you – Vlad Iobagiu Jan 4 '17 at 19:19
  • @SitecoreClimber that would be my recommended approach as well, but I think the OP is specifically looking for a way to do this without writing custom pipelines. – Zachary Kniebel Jan 4 '17 at 20:33
  • Diego, can you clarify your post a bit? Do you just not want to write a "custom pipeline" or is it "custom processors" for existing pipelines as well that you don't want to write? I may have mistakenly inferred that you didn't want to write any custom processors when I read your original post. – Zachary Kniebel Jan 4 '17 at 20:34
  • I used pipelines because this is pretty much what my searches were suggesting. My original idea is: is there a way of editing in experience editor a dictionary without writting custom code? that's the main point. I know I can write them but wondering if Sitecore wouldn't have something for us to use out of the box since Dictionaries date from Sitecore 6.X as far as I recall – Diego Jan 4 '17 at 21:18
9

As jammykam has said above I'm not aware of any OOTB way of doing this, despite dictionaries being part of Sitecore for quite some time.

I spoke to a friend who has implemented this and I thought they wrote something from scratch, but apparently they based it on the blogpost above mentioned by Sitecore Climber: http://jockstothecore.com/editable-dictionary-items-2/.

I am not sure of the changes that were made to the code for the project they used it on (or if they will be able to share it) but reading over that blog post it is definitively a good start.

A few things to consider here though:

  1. This blog post is a prototype solution and so will need some refactoring and testing.
  2. The dictionary item returned to the Experience Editor may be a fallback dictionary instead of a domain dictionary if you have fall-back enabled (this may cause you permissions problems or editors some confusion)
  3. You may need to do some work around clearing the dictionary cache after saving and publishing to see dictionary changes.

Other Options:

There is another idea here from Murali Tiruppathi that is less complex. It came from the original SDN forum post that lead to the jockstothecore blog post above being written (https://sdn.sitecore.net/Forum/ShowPost.aspx?PostID=71225):

Normally you do a sitecore translate for example:

@Sitecore.Globalization.Translate.Text("EmailForm.Validation.CCBCC") 

You can encapsulate the Translate to a custom class which might look like:

public static class CustomTranslate 
{    
    public static string Text(string key) 
    { 
        if (Sitecore.Context.PageMode.IsPageEditorEditing) 
        { 
            Item currentItem = Context.Database.GetItem(ResourcesController.ItemLookUp()[key]); 
            if (currentItem != null) 
            { 
                return FieldRenderer.Render(currentItem, "Phrase"); 
            } 
        }

        return Sitecore.Globalization.Translate.Text(key); 
    } 
} 

The CustomTranslate.Text returns a FieldRenderer in PageEdit mode else returns the Sitecore.Globalization.Translate.Text

Then in your code you can refer the translations as:

@CustomTranslate.Text("EmailForm.Validation.CCBCC") 

The Lookup can be a dictionary of Key and Item ID:

public static class ResourceController 
{ 

    public static Dictionary ItemLookUp() 
    {       
        ///get dictionary path..etc.. code not included 

        Sitecore.Data.Items.Item[] items = Sitecore.Context.Database.SelectItems("fast:" + dictionaryPath + "//*[@@templateid='{6D1CD897-1936-4A3A-A511-289A94C2A7B1}']"); 
        items.All(y => { resourceDictionary.Add(y["Key"], y.ID.Guid.ToString()); return true;} 

        return resourceDictionary;      
    } 
} 

Again this code will likely need some refactoring, for example:

Sitecore.Context.PageMode.IsPageEditorEditing

Should now be this in 8+:

Sitecore.Context.PageMode.IsExperienceEditorEditing

Doing this via Pipelines is probably a nicer and cleaner way of doing this though.

If I get chance to use this on the current project I'm on i'll try and share the production ready code. We already have a custom translate class in place to handle empty or missing dictionary items gracefully so Murali's approach would be easier for us to implement.

  • Great answer and much cleaner than the one I provided. If I am reading it correctly, it looks like this would even support the OOTB dictionary caching mechanism! I also agree that pipelines are the way to go, when possible :) +1 – Zachary Kniebel Jan 5 '17 at 19:12
  • 2
    This is how I would have approached it as well. But again, the dictionaryPath is fixed, you'd need to replicate the getTranslation pipeline to deal with fallback... but maybe that's fine and you only want users to edit the local dictionary and you can the use the domainDictionary settings from sites. – jammykam Jan 5 '17 at 22:40
  • Good to see this agreement on this as another approach. I'd like to try it if I get chance and test it on a production instance. In our case we would only want users to edit their domain dictionary as we have 6 sites running under one Sitecore instance and a Global dictionary as a fall-back for all Sites. Content editors don't have permissions to edit the default dictionary so I'd need to think about how to handle that and get the dictionary path based on the Site being edited. – Adam Seabridge Jan 5 '17 at 23:15
  • 1
    IMO the logic in CustomTranslate.Text() is flawed. If IsPageEditorEditing and returned ItemLookUp is null then it should return Translate.Text(key) not empty string i.e.the standard dictionary value which is non-editable. I've updated the code snippet to reflect this (feel free to roll it back if you think this is wrong). Not doing this means it will not show the fallback dictionary text in Edit mode. – jammykam Jan 6 '17 at 12:33
  • Great thanks @jammykam. Appreciate the feedback on this. I'd like to test this out properly at some point soon and if I do i'll post updated code. – Adam Seabridge Jan 6 '17 at 12:54
4

Using the Sitecore Dictionary

Unfortunately, custom pipelines and the like are really the only way to go for this on, AFAIK.

Sitecore.Globalization.Translate, the method for rendering out a dictionary item's value, does not run through the Field Render pipeline. As such, custom logic must be written to allow editing of the dictionary item in the Experience Editor and to actually manage the saving of the value.

Writing a Custom Sitecore Dictionary

An alternative option, though it doesn't directly answer your question, would be to create your own custom Sitecore dictionary. You would create the necessary templates, and you could write a custom MvcHelper (or control, if using webforms) to retrieve and render the value of the item by name, path, etc. Basically, you could either write access logic to mimic the OOTB Sitecore Dictionary, or you could write your own, more robust access logic. This would allow you to render your dictionary item field values the same way as you would fields of other items, thus making it possible to edit them in the Experience Editor with the same requirements and limitations as any other item.

IMHO, the biggest negative is that you would lose the benefit of Sitecore's Dictionary caching, but you could always add your own caching to help speed things along. An alternative to implementing custom caching could be to create a rendering specifically for Dictionary entries. Your custom MvcHelper/Control would then be responsible for rendering the component with the appropriate Dictionary entry as its datasource. You could then enable HTML caching for the site, set the rendering to Cacheable and set its caching to Vary by data.

  • thanks Zachary I suspect you are right too. Will leave the question open for now to see if anyone know – Diego Jan 4 '17 at 17:27

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.