OrchardCMS / Orchard

Orchard is a free, open source, community-focused Content Management System built on the ASP.NET MVC platform.
https://orchardproject.net
BSD 3-Clause "New" or "Revised" License
2.38k stars 1.12k forks source link

Tokens in projection HTML properties act on Projection content type #2728

Open orchardbot opened 12 years ago

orchardbot commented 12 years ago

brainsiq created: https://orchard.codeplex.com/workitem/18901

To reproduce:

Create a new Query with a filter for content type equals Pages.

Add a HTML list layout with {Content.ContentType} in ItemClass.

Save the Query.

Create a new Projection content item, and select the new Query.

The issue:

When displaying, rather than adding class="Page" to each list item it adds class="Projection".

Likewise if you use a custom part and implement an ITokenProvider for IContent to generate tokens for the part then you get the same behaviour. Putting a breakpoint on content.As() below shows that content is the Projection item so the chained tokens return nothing.

context.For("Content") .Token("Custom", content => content.As()) .Chain("Custom", "CustomDetails", content => content.As());

context.For("CustomDetails") .Token("Name", custom => custom != null ? custom.Property : string.Empty);

orchardbot commented 11 years ago

bsdr commented:

See also https://orchard.codeplex.com/workitem/19524

orchardbot commented 11 years ago

@sebastienros commented:

Well known behavior. Right now the solution is to use the properties to use a local class, or to create your own layout which would not make use of the List shape. Currently the list shape takes a constant for all its items, which is the actual limitation. Not using the List shape would solve your problem.

orchardbot commented 11 years ago

sirakov commented:

Hi,

My goal was to in insert an Attribute with a link on each

  • item when in a projection , so to have ..

    <li data-thumb="{TokenForImagePicker.Url.Absolute}">
    <img src="{TokenForImagePicker.Url.Absolute}">
     </li>

    I was wondering why its not working for the Attribute until I read your post (thanks a lot). So, like you suggested I created a custom list Shape with a custom layout. It's OK now but it seems to me quite dirty the way I made it. Is it this way that its supposed to be done ?

    [Shape]
            public void CustomListCarosel(dynamic Display,TextWriter Output,IEnumerable<dynamic> Items,string Tag,string Id,
                IEnumerable<string> Classes,IDictionary<string, string> Attributes,IEnumerable<string> ItemClasses,
                IDictionary<string, string> ItemAttributes, IEnumerable<string> FirstItemClasses, IEnumerable<string> OuterDivClasses, string outerDivId)
            {
    
                if (Items == null)
                    return;
                var itemDisplayOutputs = Items.Select(item => Display(item)).Where(output => !string.IsNullOrWhiteSpace(output.ToHtmlString())).ToList();
    
                var propertyWrappers = Items.Select(item => item.Items[0]).ToList();//get PropertyWrappers
                var count = itemDisplayOutputs.Count();
                if (count < 1)
                    return;
                bool setAttributes = false;
                if (ItemAttributes.All(pair => string.IsNullOrEmpty(pair.Key) && string.IsNullOrEmpty(pair.Value)))
                    ItemAttributes.Clear(); // not get exception
                if (ItemAttributes.All(pair => !string.IsNullOrEmpty(pair.Key) && string.IsNullOrEmpty(pair.Value))) {
                    setAttributes = true;
                }
                var listTagName = string.IsNullOrEmpty(Tag) ? "ul" : Tag;
                const string itemTagName = "li";
                var outerDiv = GetTagBuilder("div", outerDivId, OuterDivClasses, Attributes);
                var listTag = GetTagBuilder(listTagName, Id, Classes, Attributes);
    
                Output.Write(outerDiv.ToString(TagRenderMode.StartTag));
                Output.Write(listTag.ToString(TagRenderMode.StartTag));
                var index = 0;
                foreach (var itemDisplayOutput in itemDisplayOutputs) {
                    // get PropertyWrapper and inner link
                    dynamic propWraper = propertyWrappers[index];
                    string resultOutput = Convert.ToString(Display(propWraper.Item));
                    if (propWraper.Property.RewriteOutput) {
                        resultOutput = _tokenizer.Replace(propWraper.Property.RewriteText, new Dictionary<string, object> {{"Text", resultOutput}, {"Content", propWraper.ContentItem}});
                    }
    
                    //Get the inner link from the ResultOutput
                    var stripedlink = resultOutput.Substring(resultOutput.IndexOf("\"") + 1, resultOutput.LastIndexOf("\"") - resultOutput.IndexOf("\"")-1 );
    
                    //Construct the <li> Attribute - set the inner link ONLY if no value for it is provided
                    if (setAttributes){
                        IEnumerable<string> keys = ItemAttributes.Where(pair => pair.Key != string.Empty).Select(pair => pair.Key);
                        keys.ToList().ForEach(s => ItemAttributes[s] = stripedlink); 
                    }
    
                    var itemTag = GetTagBuilder(itemTagName, Id, ItemClasses, ItemAttributes);
                    if (index == 0)
                        itemTag.AddCssClass(FirstItemClasses.FirstOrDefault(s => !string.IsNullOrEmpty(s)));
                    if (index == count - 1)
                        itemTag.AddCssClass("last");
                    Output.Write(itemTag.ToString(TagRenderMode.StartTag));
                    Output.Write(itemDisplayOutput);
                    Output.Write(itemTag.ToString(TagRenderMode.EndTag));
                    ++index;
    
                }
    
                Output.Write(listTag.ToString(TagRenderMode.EndTag));
                Output.Write(outerDiv.ToString(TagRenderMode.EndTag));
            }
  • orchardbot commented 10 years ago

    tgelles commented:

    Is this issue still prevalent in 1.7.1?

    I've also created a projection with an HTML List Layout, and when I try to add "TaxonomyField.Terms[:*]} {TaxonomyField.Terms}" to the item class, they don't get rendered; but the other classes do.