Copied to clipboard

Flag this post as spam?

This post will be reported to the moderators as potential spam to be looked at


  • Valentin 11 posts 110 karma points
    Apr 02, 2018 @ 07:25
    Valentin
    0

    Umbraco API on Frontend

    Hello everybody! I have some requirements on my Frontend, and I try made UI on ReactJs Frontend. Another detail, I made it on https://reactjs.net/ for server rendering, and now I can't imagine how can I use on JS side Umbraco API services or as minimum, how in JSX I can got Dictionary Items for multilanguage needs in Razor View I can as ex. @Umbraco.GetDictionaryValue("SomeKey") has the analogy on JSX ?

    thank you

  • Alex Skrypnyk 5908 posts 22603 karma points MVP 4x admin c-trib
    Apr 02, 2018 @ 07:51
    Alex Skrypnyk
    0

    Hi Valentin

    Try to use Surface Controllers + Partial view combination

    return filled view with controllers to the page, in views use JSX instead of Razor

    Thanks,

    Alex

  • Valentin 11 posts 110 karma points
    Apr 02, 2018 @ 08:03
    Valentin
    0

    I'm not imagine how I can draw HTML on Razor into JSX can you explain more details?

  • Alex Skrypnyk 5908 posts 22603 karma points MVP 4x admin c-trib
    Apr 02, 2018 @ 08:15
    Alex Skrypnyk
    0

    Valentin

    How are you handling requests to the website? Is it Umbraco page?

  • Valentin 11 posts 110 karma points
    Apr 02, 2018 @ 08:30
    Valentin
    0

    it is ASP.NET page than render something like @Html.React("ReactComponent", new { data = Model })

  • Valentin 11 posts 110 karma points
    Apr 02, 2018 @ 09:29
    Valentin
    0

    As solution, but very ugly, I can render al dictionary keys and values to window dictionary, and on client side use them, but is bad because increase traffic (page size); another way, make any http handler with cache to get dictionary as some js file, that shall generated on fly from Umbraco data

  • Alex Skrypnyk 5908 posts 22603 karma points MVP 4x admin c-trib
    Apr 02, 2018 @ 09:34
    Alex Skrypnyk
    0

    So you are using html views instead of Razor?

    You can render html with SurfaceController, the issue is that you haven't access to UmbracoHelper inside html code, right?

  • Valentin 11 posts 110 karma points
    Apr 02, 2018 @ 09:36
    Valentin
    0

    right, I have jsx file (like js) with html embeded into it I can not use razor helpers

  • Alex Skrypnyk 5908 posts 22603 karma points MVP 4x admin c-trib
    Apr 02, 2018 @ 12:24
    Alex Skrypnyk
    0

    Can you avoid of using @Html.React("ReactComponent", new { data = Model }) helper?

    You can use render Partial or render view razor helper and use Umbraco context inside this view

  • Valentin 11 posts 110 karma points
    Apr 02, 2018 @ 14:52
    Valentin
    0

    unfortunately no, because react & JSX inseparable

  • Valentin 11 posts 110 karma points
    Apr 02, 2018 @ 16:56
    Valentin
    0

    I think best solution be use umbraco event, and when dictionary items changed, re-generate js file, with content initializer via JSON like: module.exports = [ {key:.., value ...}, .. ] and after that, I can include that JS file to my webpack chain to use and on server rendering side and client (browser) side

  • Alex Skrypnyk 5908 posts 22603 karma points MVP 4x admin c-trib
    Apr 02, 2018 @ 17:41
    Alex Skrypnyk
    0

    Valentin, you can download all dictionary to csv with this package - https://www.diplo.co.uk/blog/web-development/diplo-dictionary-editor-for-umbraco/

  • Alex Skrypnyk 5908 posts 22603 karma points MVP 4x admin c-trib
    Apr 05, 2018 @ 16:21
    Alex Skrypnyk
    0

    Hi Valentin

    Did you solve the issue? Can you share with the community?

    Thanks,

    Alex

  • Dave Woestenborghs 3325 posts 11170 karma points MVP 5x admin c-trib
    Apr 05, 2018 @ 17:57
    Dave Woestenborghs
    0

    Hi Valentin,

    We solved this by passing in the dictionary items as well to the react component.

    Then you get something like this :

        @Html.React("ReactComponent", 
        new { data = Model, 
        labels = new {
                        firstname = Umbraco.GetDictionaryValue("firstname"),
                        lastname = Umbraco.GetDictionaryValue("lastname")
    }
    })
    

    And then in your react component you can access all the values throught the labels prop.

    Dave

  • Valentin 11 posts 110 karma points
    Apr 05, 2018 @ 18:11
    Valentin
    100

    I made Observer singleton class that subscribe to appropriate events and auto generate JSON object

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Web;
    using Umbraco.Core;
    using Umbraco.Core.Services;
    using Umbraco.Web;
    
    namespace WinePortal.Core
    {
        public class LocalizationServiceObserver
        {
            public static string ScriptPath { get; private set; }
    
            public static void Subscribe(string scriptPath)
            {
                ScriptPath = scriptPath;
    
                LocalizationService.SavedLanguage += UpdateDictionaryScript;
                LocalizationService.DeletedLanguage += UpdateDictionaryScript;
                LocalizationService.DeletedDictionaryItem += UpdateDictionaryScript;
                LocalizationService.SavedDictionaryItem += UpdateDictionaryScript;
            }
    
            private static void UpdateDictionaryScript(ILocalizationService sender, object e)
            {
                StringBuilder scriptBuilder = new StringBuilder("var UmbDictionary = {\r\n");
                foreach (var language in sender.GetAllLanguages())
                {
                    var culture = language.CultureInfo.Name;
                    scriptBuilder.AppendLine($"\"{culture}\": [");
    
                    var items = GetDictionaryItems(culture);
                    foreach (var dictionaryItem in items)
                    {
                        var key = HttpUtility.JavaScriptStringEncode(dictionaryItem.Key);
                        var value = HttpUtility.JavaScriptStringEncode(dictionaryItem.Value);
                        scriptBuilder.AppendLine($"{{ \"Key\": \"{key}\", \"Value\": \"{value}\" }},");
                    }
    
                    scriptBuilder.AppendLine("],");
                }
                scriptBuilder.AppendLine("};");
                System.IO.File.WriteAllText(ScriptPath, scriptBuilder.ToString());
            }
    
            public static IEnumerable<DictionaryItem> GetDictionaryItems(string culture)
            {
                //For now, we're only going to get the English items
    
                var dictionary = new List<DictionaryItem>();
    
                var root = ApplicationContext.Current.Services.LocalizationService.GetRootDictionaryItems();
    
                if (!root.Any())
                {
                    return Enumerable.Empty<DictionaryItem>();
                }
    
                foreach (var item in root)
                {
                    dictionary.Add(new DictionaryItem
                    {
                        Key = item.ItemKey,
                        Value = item.Translations.Where(x => x.Language.CultureInfo.Name == culture).Select(x => x.Value).FirstOrDefault()
                    });
    
                    dictionary.AddRange(LoopThroughDictionaryChildren(item.Key, culture));
                }
    
                return dictionary;
            }
    
            private static IEnumerable<DictionaryItem> LoopThroughDictionaryChildren(Guid key, string culture)
            {
                var dictionary = new List<DictionaryItem>();
                var items = ApplicationContext.Current.Services.LocalizationService.GetDictionaryItemChildren(key);
    
                if (!items.Any())
                {
                    return Enumerable.Empty<DictionaryItem>();
                }
    
                foreach (var subItem in items)
                {
                    dictionary.Add(new DictionaryItem
                    {
                        Key = subItem.ItemKey,
                        Value = subItem.Translations.Where(x => x.Language.CultureInfo.Name == culture).Select(x => x.Value).FirstOrDefault()
                    });
    
                    dictionary.AddRange(LoopThroughDictionaryChildren(subItem.Key, culture));
                }
    
                return dictionary;
            }
        }
    
    
    
        public class DictionaryItem
        {
            public string Key { get; set; }
    
            public string Value { get; set; }
        }
    }
    

    usage example

    protected override void ApplicationStarted(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext)
            {
                var scriptPath = UmbracoContext.Current.HttpContext.Server.MapPath("~/scripts/UmbDictionary.generated.js");
                LocalizationServiceObserver.Subscribe(scriptPath);
            }
    

    this is more universal approach

  • This forum is in read-only mode while we transition to the new forum.

    You can continue this topic on the new forum by tapping the "Continue discussion" link below.

Please Sign in or register to post replies