Copied to clipboard

Flag this post as spam?

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


  • MiloW 10 posts 90 karma points
    Jan 14, 2022 @ 21:40
    MiloW
    0

    Dynamic links with dynamic title and even label?

    Tried on FB but no luck...

    I have a question.

    When I link an internal page with the linking 'system', e.g. a contact us page - it inputs /{localLink:umb://document/ec975190c0314832a16668e02e0916c5} as the link but of course it "translates" it then to different languages when I copy a component config or even HTML - that is awesome.

    My question is - is it possible to make Umbraco input the title for this link (and ideally - what's between also but title is crucial)?

    So for example I create

    <a href="/{localLink:umb://document/ec975190c0314832a16668e02e0916c5}" title="{somethinghere1}">{somethinghere2}</a>
    

    and then it automatically would show up, given I have a menu item "Contact Us" for English and "Kontakt" for German translation of the page:

    • for the English version: Contact Us link with a title "Contact Us" and leading to the Contact Us page
    • for e.g. German: Kontakt link with a title Kontakt and leading to Kontakt page

    You know, like a totally dynamic link to a page, but not only the source is dynamic, also it makes the title from the title of the page and maybe even echoes the name of the page?

    Let's say title would be great, the text of the link would be awesome.

    Is it possible?

  • Mark Drake 133 posts 457 karma points c-trib
    Jan 15, 2022 @ 23:20
    Mark Drake
    0

    I wrote something that I'm sure is absolutely terrible performance-wise.

    The idea was to use a regex to find any hints in the RTE editor for dynamic values. An example would be {{name}}. For each match my code would (first) reflect back on the object to see if any properties match this value, and (last) check the content for any properties.

    This is just theory and hasn't been tested in a production website yet. Hasn't been thoroughly tested in development either. There are some things I would want to change:

    • Obviously the code is pretty incompetent. I'm sure there's a better way to do everything I did.
    • I'd prefer if Parse didn't require any arguments (the currently assigned content item) but I couldn't find a way to do dependency injection in my static extension class. The currently assigned content item could instead be the default.
    • You could override the default by providing your own IPublishedContent to the Parse method.
    • Prioritize the Umbraco content property first, and as a last resort reflect on the C# object. Just for performance reasons.
    • Extend other properties (at least strings) so we can parse dynamic values in them as well.

    Here is RteParser.cs:

    /*
     * Ref: https://github.com/umbraco/Umbraco-CMS/blob/5bfab13dc5a268714aad2426a2b68ab5561a6407/src/Umbraco.Core/Templates/HtmlLocalLinkParser.cs
     * Ref: https://stackoverflow.com/questions/36977442/how-to-to-transform-a-string-of-property-names-into-an-objects-property-values
     */
    using System.Text.RegularExpressions;
    using Umbraco.Cms.Core.Models.PublishedContent;
    using Umbraco.Cms.Core.Strings;
    using System.Reflection;
    using Umbraco.Cms.Web.Common;
    
    namespace Humble.Umbraco.Parsers
    {
    public static class IHtmlEncodedStringExtensions
    {
        private static readonly Regex ReplacePattern = new Regex(@"{{([a-zA-Z]+)}}", RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace);
    
        public static IHtmlEncodedString Parse(this IHtmlEncodedString Html, IPublishedContent Content)
        {
            // Exit: string contents are null or empty
            if (Html == null) return Html;
    
            // Exit: no current asigned content item
            if (Content == null) return Html;
    
            // Find matches
            MatchCollection matches = ReplacePattern.Matches(Html.ToString());
    
            // Exit: no matches
            if (matches.Count.Equals(0)) return Html;
    
            // Build new string from model data
            var type = Content.GetType();
            string newContents = Html.ToString();
    
            // Begin replacing values
            foreach (Match match in matches)
            {
    
                // Check object properties first
                string key = match.Groups[1].Value;
                PropertyInfo typeProperty = type.GetProperty(key, BindingFlags.IgnoreCase | BindingFlags.Instance | BindingFlags.Public);
    
                if (typeProperty != null)
                {
                    newContents = newContents.Replace(match.Value, typeProperty.GetValue(Content, null).ToString());
                    continue;
                }
    
                // Check content properties last
                var contentProperty = Content.GetProperty(key);
                if (contentProperty == null) continue;
    
                object value = contentProperty.GetValue();
                if (value == null) continue;
    
                newContents = newContents.Replace(match.Value, value.ToString());
            }
    
            // Return replaced values
            return new HtmlEncodedString(newContents);
        }
    }
    }
    

    Feel free to update the namespace. Then add the reference to your _ViewImports.cshtml file. Here's mine:

    @using Umbraco.Extensions
    @using HumbleUmbraco
    @using Umbraco.Cms.Web.Common.PublishedModels
    @using Umbraco.Cms.Web.Common.Views
    @using Umbraco.Cms.Core.Models.Blocks
    @using Humble.Umbraco.Parsers
    @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
    

    This is how I referenced it via a strongly typed model from a razor partial file:

    @inherits UmbracoViewPage<BlockListItem>
    @{
    if (Model == null)
    {
        return;
    }
    
    var content = (Humble_Element_RichText)Model.Content;
    var settings = Model.Settings;
    }
    
    @Html.Raw(content.Copy.Parse(Umbraco.AssignedContentItem))
    
  • MiloW 10 posts 90 karma points
    Jan 16, 2022 @ 13:31
    MiloW
    0

    I am not a programmer so I understand maybe 15 per cent of what you've written : )

    I understand the problem, I think.

    Can't we take advantage on the engine that's already there?

    Because some code takes advantage of the translation engine, looking for the given page I believe this is the

    /{localLink:umb://document/ec975190c0314832a16668e02e0916c5}
    

    code. So when you input it, it links to the proper page, in the currently viewed language. So the mechanics is ready, I guess?

    Can't we, based on what was found, just "load" this page's meta title and just input it where title=" " is and before the closing of the HTML link?

    This, I feel, wouldn't need extensive querying, just take more data based on localLink? Because it definitely takes the "href" part... can't it take what's in the meta title and input it in two places?

  • Mark Drake 133 posts 457 karma points c-trib
    Jan 18, 2022 @ 17:24
    Mark Drake
    0

    Actually my code above won't work for your specific use case, but it is an example of how to add some dynamic text to an RTE field.

    If I understand you correctly, my takeaway is this short user story:

    • When I insert a link from the RTE
    • If the link is local to Umbraco
    • I want the title of the link to be dynamic, just like the URL

    I'd say that you're absolutely right and that somebody should bring this up as a discussion item on GitHub. If I insert a link, and don't type specific text as a title, then the title should be dynamic.

    How {localLink} currently works...

    Umbraco wrote a parser just for {localLink}. Before the data even reaches your razor HTML, where you write HTML to send to the client, it's already been parsed/transformed to the actual URL.

    But they don't insert any other information. There's no placeholders for other things like the title of the page.

    Let me play around with this and see if there's anything more I can do without actually making changes to Umbraco itself. But I think someone should discuss this on GitHub and recommend a change in the way local links are added to the RTE and parsed for the frontend.

  • MiloW 10 posts 90 karma points
    Jan 18, 2022 @ 18:55
    MiloW
    0

    Cool, I am happy that you see a point in this idea.

    Me, working on a 12-language website (as a webmaster/content administrator), I am trying to find solutions or shortcuts that will help me ease my job...

Please Sign in or register to post replies

Write your reply to:

Draft