Question

I'm a little padavan when it comes to coding;) I looked for the following codes via google and pieced them together;) but now of course I have reached my limits;) I have a Sharpoint Grouped Listview; Is it possible or can someone give me a tip how I can manage it: if user is not in group16 hide the list content row belongs to Collumn(Type=done)! Thx Max

enter code here
<script src="/sites/09272/VDB/SiteAssets/jquery-3.5.1.min.js" type="text/javascript"></script>
<script src="/sites/09272/VDB/SiteAssets/jquery.SPServices-2014.02.min.js" type="text/javascript"></script>

<script type="text/javascript">


SP.SOD.executeFunc("clienttemplates.js", "SPClientTemplates", function() {
Group16();

   SPClientTemplates.TemplateManager.RegisterTemplateOverrides({
     OnPostRender: function(ctx) {

       var statusColors =  {
          'active' : '#82E0AA',  
          'idle' :  '#F1C40F'

       };

       var statusDisplay =  {
          'done' :  'none'

       };

       var rows = ctx.ListData.Row;
       for (var i=0;i<rows.length;i++)
       {
          var status = rows[i]["Type"];
          var rowId = GenerateIIDForListItem(ctx, rows[i]);
          var row = document.getElementById(rowId); 
          row.style.backgroundColor = statusColors[status]; // color for Test
          row.style.display = statusDisplay[status]; // hidden 
       }
     }
   });



});



function Group16() {
        var userId = _spPageContextInfo.userId;
            var groupId = 16;
                var requestHeaders = { "accept" : "application/json; odata=verbose" };
            var columnName="Typ";
            var Status = $(".ms-standardheader:contains('"+columnName+"')").closest('td').next().text().trim();
        
            $.ajax({
                    url : _spPageContextInfo.webAbsoluteUrl + "/_api/web/sitegroups(" + groupId + ")/users/getbyid(" + userId + ")",
                        contentType : "application/json;odata=verbose",
                    headers : requestHeaders,
                    success : userAdmin,
                        error : userNotAdmin
                });
         
                function userAdmin(data, request){
                            //alert("In Group: 16");
                    }

                    function userNotAdmin(error) {
                            //alert("Not in Group: 16");
                    
                    }


}




    function expandGroups() {
        $("img[id^='img_']").click();
    }

</script>

<body onload="expandGroups();">
</body>
Was it helpful?

Solution

This gets a little tricky because the CSR cycle happens very early as a page is loading (it is rendering the contents of the page, after all), and making an AJAX request to SharePoint for additional data takes a while (in computer time), and it's very difficult to get the CSR process to wait for an asynchronous call to the server.

So usually, my approach (as I've mentioned here, and probably other places too) is to use CSR to set yourself up with placeholders that you can easily locate later, and after your AJAX call is complete, then locate your placeholders and take whatever action you need to based on the result.

Looking at what you've got going on there, it looks like you are doing some conditional coloring of rows based on a column value, as well as trying to hide the rows where the Type column is "done". It also looks like you are using jQuery, which is helpful because you can use jQuery's $(document).ready() function to execute code that needs the whole page to be rendered and all DOM elements available (i.e. after the CSR cycle is complete).

So given all that, here's the approach I would take:

  • Move the attempt to hide the rows you want to hide out of the CSR OnPostRender function, because you won't be able to tell the user's group membership in there, just let that handle the conditional color coding.
  • Use the regular CSR field rendering for the Type field to set yourself up to be able to easily find the rows that you want to hide based on the Type value.
  • Change the logic of how you think about what you are doing - instead of thinking "if the user is not in the 16 group, hide the rows", think instead "hide the rows, then if the user is in the 16 group, reveal the hidden rows". The reason you want to think this way is because ultimately, if a user is not in the 16 group you don't want them to see those rows. What happens if the AJAX call to check the group fails? If you are waiting for that result before you hide anything, then if that result never comes, the rows stay visible and anyone can see them. If you hide them initially (no matter what), then wait for the result, if the result never comes, the worst that happens is that someone who should have permission to see something doesn't see it. But you are safe in that users who do not have permission to see that data will also not see it, because you hid it straight away.
  • Get rid of that Group16 function, all that code will get moved into the jQuery $(document).ready() function.
  • Also get rid of the <body onload="expandGroups()"></body>. If you are loading all that code on to the page the way I think you are, having a <body> tag there is redundant (and bad HTML), and in any case, the $(document).ready() function is essentially the same. Even if the timing for that doesn't work in $(document).ready(), there are other, better ways than adding a <body> element with an onload attribute.
<script src="/sites/09272/VDB/SiteAssets/jquery-3.5.1.min.js" type="text/javascript"></script>
<script src="/sites/09272/VDB/SiteAssets/jquery.SPServices-2014.02.min.js" type="text/javascript"></script>

<script type="text/javascript">
SP.SOD.executeFunc("clienttemplates.js", "SPClientTemplates", function () {

    function renderTypeField(ctx) {

        // get the value of the Type column
        var typeFieldValue = ctx.CurrentItem[ctx.CurrentFieldSchema.Name];

        // if the value is "done", which we want to hide,
        // then wrap the field value in a div we can
        // easily find later.  can't use "id" here because
        // ids should be unique, and there are potentially
        // more than one row with the value "done", so instead
        // use a unique class name that we can use on multiple elements
        
        if (typeFieldValue === 'done') {
            return "<div class='type-is-done'>" + typeFieldValue + "</div>";
        } else {
            // just return the field value
            return typeFieldValue;
        }
    }

    SPClientTemplates.TemplateManager.RegisterTemplateOverrides({
        Templates: {
            Fields: {
                'Type': {
                    View: renderTypeField
                }
            }
        },
        OnPostRender: function (ctx) {

            var statusColors = {
                'active': '#82E0AA',
                'idle': '#F1C40F'
            };

            // forget about doing this here
            // var statusDisplay = {
            //     'done': 'none'
            // };

            var rows = ctx.ListData.Row;
            for (var i = 0; i < rows.length; i++) {
                var status = rows[i]["Type"];
                var rowId = GenerateIIDForListItem(ctx, rows[i]);
                var row = document.getElementById(rowId);
                row.style.backgroundColor = statusColors[status]; // color for Test
                
                // forget about doing this here
                // row.style.display = statusDisplay[status]; // hidden 
            }
        }
    });
});

// define this function to be called once the page is loaded
function expandGroups() {
    $("img[id^='img_']").click();
}

// this will fire when the full page is loaded,
// which is _after_ the rendering, so all those
// custom divs with the class "type-is-done" should
// be ready and findable on the page
$(document).ready(function() {

    // first, hide all the rows where Type is "done"
    $('div.type-is-done').closest('tr').hide();

    // check for group membership
    var userId = _spPageContextInfo.userId;
    var groupId = 16;
    var requestHeaders = { "accept": "application/json; odata=verbose" };
    
    // not sure what these two lines were supposed to do, you can probably omit them
    // var columnName = "Typ";
    // var Status = $(".ms-standardheader:contains('" + columnName + "')").closest('td').next().text().trim();

    $.ajax({
        url: _spPageContextInfo.webAbsoluteUrl + "/_api/web/sitegroups(" + groupId + ")/users/getbyid(" + userId + ")",
        contentType: "application/json;odata=verbose",
        headers: requestHeaders,
        success: userAdmin,
        error: userNotAdmin
    });

    function userAdmin(data, request) {
        //alert("In Group: 16");

        // success, user is in group, so reveal the hidden rows
        $('div.type-is-done').closest('tr').show();
    }

    function userNotAdmin(error) {
        //alert("Not in Group: 16");

        // fail - user is not in group, but rows are already hidden
        // so we don't have to do anything
    }

    // call your expand groups function
    expandGroups();
});
</script>
Licensed under: CC-BY-SA with attribution
Not affiliated with sharepoint.stackexchange
scroll top