Copied to clipboard

Flag this post as spam?

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


  • Daniel Larsen 116 posts 381 karma points
    Sep 12, 2014 @ 15:59
    Daniel Larsen
    0

    How to sort news by choosen item in a dropdown? u7

    Hi :-)

    I want to be able to sort my news by category, so I made a custom datatype dropdown with the categories and attached it to my news items and made it mandatoy to choose a category. 

    On the front end, I want a dropdown with the categories and when the user chooses a category, the page should refresh and only show the news in that category.

    I used this example (see below) to get the categories to show on my page in a dropdown, but I dont know what to do now. Can you please help me?

    http://our.umbraco.org/wiki/reference/umbracolibrary/getprevalues

    (Don't know why the option is disabled, so I enabled it.)

    @using umbraco.MacroEngines
    @inherits DynamicNodeContext @using System.Xml.XPath
    @{
    <select name="myName" id="myElementID">
    <option value="">Choose Content</option>
      @try
          {
            var baseNode = Model.AncestorOrSelf();
            XPathNodeIterator iterator = umbraco.library.GetPreValues(1091);
            iterator.MoveNext(); //move to first
            XPathNodeIterator preValues = iterator.Current.SelectChildren("preValue", "");
            @*@preValues.Count*@
                while (preValues.MoveNext())
                {
                    string preValue = preValues.Current.Value;
                    <option value="@preValue">@preValue</option>              
                }
            }
            catch (Exception e)
            {
              @e.ToString()   
            }
    </select>
    
    }
    
    Thank you for the help!
    /Daniel
  • Daniel Larsen 116 posts 381 karma points
    Sep 15, 2014 @ 10:23
    Daniel Larsen
    0

    Does anyone know if it is possible? :-)

    /Daniel

  • Steve Morgan 1349 posts 4459 karma points c-trib
    Sep 15, 2014 @ 11:27
    Steve Morgan
    1

    Hi Daniel,

    If you're doing a full page reload then this can be done in Razor quite simply. You need to pass a URL parameter to the page and then read that in the Partial View Macro and use this in your filter. I've knocked together a quick example for you - it needs tightening up (it's case sensitve at the moment). 

    Below will allow urls like: www.mydomain.com/news?newsCategory=news  and this will filter the articles (aka newsItems!). You just need to change the logic of your page to GET on category dropdown change (easy in JS) to the same URL. 

    @inherits Umbraco.Web.Macros.PartialViewMacroPage
    
    
        @{
            var homepage = CurrentPage.AncestorsOrSelf(1).First();
            @* now we need to tell Umbraco to get the News container parent *@
            var newsContainer = homepage.ArticlesMain.First();
            @* Get the category from the parameter *@
            var newsCategory = Request.Params["newsCategory"];
    
    
            @* OrderBy() takes the property to sort by and optionally order desc/asc *@
            @* for each article item (note plural!) under the newsContainer *@
    
            @* build up your filter string  *@
            string filter = "Visible";
            if (newsCategory != null) 
            {
                filter = String.Concat("Visible && newsCategory = \"", newsCategory, "\"");
            }
            @* remove me - testing only! *@
            @:<h1>Filter: @filter</h1>
    
            var newsItems = newsContainer.ArticlesItems.Where(filter).OrderBy("CreateDate desc");
    
            foreach (var newsItem in newsItems)
            { 
                <div class="article">
                    <div class="articletitle"><a href="@newsItem.Url">@newsItem.Name</a></div>
                    <h2>@newsItem.newsCategory</h2>
                    <div class="articlepreview">@Umbraco.Truncate(@newsItem.ArticleContents,100) <a href="@newsItem.Url">Read More..</a></div>
                </div>
                <hr/>
            }

     

    That would work - if you want an AJAX load where the user stays on the same page then you can either create an API and get JSON (using JQuery / JS to output) from Umbraco (I think it's this link but Umbraco.tv is down at the moment) or (more hacky) return JSON in a partial view Macro http://stackoverflow.com/questions/12817266/output-json-with-umbraco-template-using-razor

  • Daniel Larsen 116 posts 381 karma points
    Sep 15, 2014 @ 14:31
    Daniel Larsen
    0

    Thank you very much for your answer!  I cant seem to get it working though, but I think it is my jquery that fails. Can you show me your JS/jquery?

    /Daniel

  • Steve Morgan 1349 posts 4459 karma points c-trib
    Sep 15, 2014 @ 16:16
    Steve Morgan
    1

    Does it work if you just manually add a url parameter in the browser?

     

    I should have note you need to change the document type aliases to match the ones in your system. E.g. ArticlesMain and articlesItems. Note the plural on the items too. E.g. if your News items alias is "news item" then use newsItems (where you set the news items var). 

     

     

  • Daniel Larsen 116 posts 381 karma points
    Sep 17, 2014 @ 10:15
    Daniel Larsen
    0

    Sorry for the late answer. I am glad you take the time to help med :-)

    I did change the aliases and remembered the plural. The filter you made, displays the category correctly, but i still think it is my JS that fails.

    JS:

    $("#newsCategory").change(function() {
    var url = $(location).attr('href');
    var str = $("option:selected", this).text();
    $(location).attr('href',url + "?newsCategory=" + str);
    });

    Razor:

    @{
            var homepage = Model.First();
            @* now we need to tell Umbraco to get the News container parent *@
            var newsContainer = homepage.NewsArticle.First();
            @* Get the category from the parameter *@
            var newsCategory = Request.Params["newsCategory"];

            @* OrderBy() takes the property to sort by and optionally order desc/asc *@
          @* for each article item (note plural!) under the newsContainer *@

            @* build up your filter string  *@
            string filter = "Visible";
            if (newsCategory != null) 
            {
                filter = String.Concat("Visible && newsCategory = \"", newsCategory, "\"");
            }
            @* remove me - testing only! *@
            @:<h1>Filter: @filter</h1>

            var newsItems = newsContainer.NewsArticles.Where(filter).OrderBy("CreateDate desc");

            foreach (var newsItem in newsItems)
            { <div class="article"> <div class="articletitle"><a href="@newsItem.Url">@newsItem.Name</a></div> <h2>@newsItem.newsCategory</h2> <div class="articlepreview">@Truncate(newsItem.Content,100) <a href="@newsItem.Url">Read More..</a></div> </div> <hr/> } }

    Does this help?

  • Steve Morgan 1349 posts 4459 karma points c-trib
    Sep 17, 2014 @ 11:38
    Steve Morgan
    1

    Hi,

    Hard to debug JS over a forum - I'll take a couple of guesses though :) 

    I take it you've got Jquery working on this page and putting an alert(url); line in your JS works (e.g. you're checking that this change is being executed and there are no issues with JQuery and no errors in the console if you use Firebug / Chrome dev tools?

    I'd add the function below and rework your JS to something like:

    $(document).ready(function(){
        $("#newsCategory").change(function() {
            var url = window.location.pathname;  // use this not location as jquery says this is unsupported - plus this is minus the "old" url param
            var str = $("option:selected", this).text();
            window.location.href= url + "?newsCategory=" + htmlEscape(str);
        });
    });
    
    function htmlEscape(str) {
        return String(str)
                .replace(/&/g, '&amp;')
                .replace(/"/g, '&quot;')
                .replace(/'/g, '&#39;')
                .replace(/</g, '&lt;')
                .replace(/>/g, '&gt;');
    }
    

    The reasons for the changes:

    • if you use $(location).attr('href'); it will keep adding on the URL parameter (so duplicate params are added).
    • You need to html encode the str if you have spaces etc in your values in the HTML select. 
    • Apparently location isn't supported in JQuery (even though everyone uses it!). I'm not entirely sold on this but pure JS can't hurt.

     

    Also - check that your HTML in the select looks something like (e.g. you have a value attribute - I'd recommend this is actually what you pass and use in your filters rather than the user visible text):

    <select id="newsCategory"> <option value="1">Test</option> <option value="2">Item 2</option> <option value="3">Item 3</option> </select>

     

  • Daniel Larsen 116 posts 381 karma points
    Sep 17, 2014 @ 13:46
    Daniel Larsen
    0

    You JS works perfectly! But it still doesnt work...

    This macro will be placed on the news page. Here is the structure of my news.

    Home

    -News

    --Year

    ---Month

    ----NewsArticle

    ----NewsArticle

    ----NewsArticle

    @{
            @*var homepage = Model.AncestorOrSelf(1);*@
            @* now we need to tell Umbraco to get the News container parent *@
            var newsContainer = Model;
            @* Get the category from the parameter *@
            var newsCategory = Request.Params["newsCategory"];
    
    
            @* OrderBy() takes the property to sort by and optionally order desc/asc *@
            @* for each article item (note plural!) under the newsContainer *@
    
            @* build up your filter string  *@
            string filter = "Visible";
            if (newsCategory != null) 
            {
                filter = String.Concat("Visible && newsCategory = \"", newsCategory, "\"");
            }
            @* remove me - testing only! *@
            @:<h1>Filter: @filter</h1>
    
            var newsItems = newsContainer.Descendants("NewsArticle").Where(filter).OrderBy("CreateDate desc");
    
            foreach (var newsItem in newsItems)
            { 
    
                    <a href="@newsItem.Url">@newsItem.Name</a>
                    <h2>@newsItem.newsCategory</h2>
                    <div>@Truncate(newsItem.Content,100) <a href="@newsItem.Url">Read More..</a></div>
    
            }
    }
    

    Right now there is not being shown any news, with or without a selection. I cant see the smoking gun and your code makes sense... I am lost!

    Again thank you for taking your time to help me :-)

  • Steve Morgan 1349 posts 4459 karma points c-trib
    Sep 17, 2014 @ 14:43
    Steve Morgan
    100

    Right you need to do some debugging. I take it we're not getting an error (syntax or similar) out on the page from the Macro but just check the log. Look at the Umbraco log in /app_data/logs/umbracotracellog.txt  - see if there is an error in there.

    If that looks clear let's debug to screen. Do the following:

    1)  Rule out the filter causing an issue - add the line after the closing brace on the if 

    filter = "true == true";

    If we've still not got any resutls then we've got an issue in the aliases. 
     

    2) Let's check we've got some articles? 

    @:<h2> We have : @newsItems.Count() </h2>

    3) Let's check we are actually getting the news container

    @:<h2> Checking we have a news container: @newsContainer.Id - @newsContainer.Name </h2>

     

    So putting it all together (using my document type names... remember yours might have slightly different names *including* case differences...

    @inherits Umbraco.Web.Macros.PartialViewMacroPage
    
    
        @{
            var homepage = CurrentPage.AncestorsOrSelf(1).First();
            @* now we need to tell Umbraco to get the News container parent *@
            var newsContainer = homepage.ArticlesMain.First();
            @* Get the category from the parameter *@
            var newsCategory = Request.Params["newsCategory"];
    
    
            @* OrderBy() takes the property to sort by and optionally order desc/asc *@
            @* for each article item (note plural!) under the newsContainer *@
    
            @:<h2> Checking we have a news container: @newsContainer.Id - @newsContainer.Name </h2>
    
            @* build up your filter string  *@
            string filter = "Visible";
            if (newsCategory != null) 
            {
                filter = String.Concat("Visible && newsCategory = \"", newsCategory, "\"");
            }
            @*remove me - debugging *@
            filter = "true == true";
            @* remove me - testing only! *@
            @:<h1>Filter: @filter</h1>
            @:<h1>@newsContainer.Id</h1>
            var newsItems = newsContainer.ArticlesItems.Where(filter).OrderBy("CreateDate desc");
    
            @* do we have any articles? *@
            @:<h2> We have : @newsItems.Count() </h2>
    
            foreach (var newsItem in newsItems)
            { 
                <div class="article">
                    <div class="articletitle"><a href="@newsItem.Url">@newsItem.Name</a></div>
                    <h2>@newsItem.newsCategory</h2>
                    <div class="articlepreview">@Umbraco.Truncate(@newsItem.ArticleContents,100) <a href="@newsItem.Url">Read More..</a></div>
                </div>
                <hr/>
            }
        }
    
    You should get something like:

    Checking we have a news container: 1059 - Articles

    Filter: true == true

    1059

    We have : 3

  • Daniel Larsen 116 posts 381 karma points
    Sep 19, 2014 @ 09:05
    Daniel Larsen
    0

    Thank you! It was the filter that was causing the problem. I forgot to change newsCategory to my category alias.

    You have been a great help and I truely appreciate you taking your time to help me!

    I hope you'll have a great weekend! :-D

    /Daniel

  • Steve Morgan 1349 posts 4459 karma points c-trib
    Sep 19, 2014 @ 09:17
    Steve Morgan
    0

    Glad you fixed it! 

     

    Steve

Please Sign in or register to post replies

Write your reply to:

Draft