3

Please Help!

I have a custom list with 3 columns, "Slno","Language","Status".Status is a choice field with choices "Ongoing" and "Terminated". The Color of the "Language" column changes based on the "status" column value.

enter image description here

CODE:

(function () {

    var StatusFieldContext = {}; 
    StatusFieldContext.Templates = {};
    StatusFieldContext.Templates.Fields = {
        "Language": {"View": ColorFiledTemplate}
    };   
    SPClientTemplates.TemplateManager.RegisterTemplateOverrides(StatusFieldContext);
})();
function ColorFiledTemplate(ctx) {

    var  lang = ctx.CurrentItem.Language;
    var  st = ctx.CurrentItem.Status; 

    switch (st) {
        case "Ongoing":
            return "<span style='background-color: #65FE18;display:block;width:200px;height:35px;'>" + lang + "</span>";           
            break;
        case "Terminated":
            return "<font style='background-color:#FF2402;display:block;width:200px;height:35px;'>"+ lang +"</font>";
            break;     
    }
}

Real Problem: I DO NOT want to display the field "Status". I tried modifying the view by not selecting the "Status"field. If I do so, nothing appears in the Language column.(Screenshot Attached).

enter image description here

What do I do to display only "Slno" and "Language" field? How do I write the script?

FYI: I'm using Script Editor to link the Javascript code to this page.

3 Answers 3

1

So your rendering problem stems from the fact that in order to get a field's value on ctx.CurrentItem during rendering, you must include that column in the view.

However, in your case, you need values from a certain column, but don't want that column seen in the view. So I think in your case, something like what Stan is suggesting will work, although I'd advise finding the column index dynamically, in case the field order changes in the view. I would do that in a post-render function.

So in the part of your script where you are registering the override, I would add:

StatusFieldContext.OnPostRender = hideStatusColumn;

And then create another function:

function hideStatusColumn(ctx) {
    var positionOfStatusColumn = 0;
    // get all the headers
    var headers = document.querySelectorAll('.ms-listviewtable th');
    // loop through the headers and find your column
    // based on matching the DISPLAY name
    var len = headers.length;
    for (var i = 0; i < len; i++) {
        if (headers[i].innerHTML.indexOf('Status') != -1) {
            // we found the Status column!
            // but because :nth-child is 1-based not zero-based, we need to add one
            positionOfStatusColumn = i + 1;
        }
    }

    // now that we know the position of the Status column, we can hide all the cells

    // only one header, so we can use querySelector
    document.querySelector('.ms-listviewtable th:nth-child(' + positionOfStatusColumn + ')').style.display = 'none';

    // have to get all the regular td cells, so we have to use querySelectorAll
    document.querySelectorAll('.ms-listviewtable td:nth-child(' + positionOfStatusColumn + ')').forEach(function (cell) {
        cell.style.display = 'none';
    });
}

In response to your comment, in order to hide multiple columns, you would have to just find the positions of those columns also as you are looping through the headers, based on their full display names. Then just repeat the same code to set display:none on the other cells. Here's an updated function as an example. I have also added a check to make sure you actually found the column in the view before trying to hide it, so you don't accidentally hide something you don't want to touch:

function hideMultipleStatusColumns(ctx) {
    // initialize the variables as null so we can
    // check to make sure we found values later
    var positionOfStatus1Column = null;
    var positionOfStatus2Column = null;
    var positionOfStatus3Column = null;
    // get all the headers
    var headers = document.querySelectorAll('.ms-listviewtable th');
    // loop through the headers and find your columns
    // based on matching the DISPLAY name
    var len = headers.length;
    for (var i = 0; i < len; i++) {
        if (headers[i].innerHTML.indexOf('Status 1') != -1) {
            // we found the Status 1 column!
            // but because :nth-child is 1-based not zero-based, we need to add one
            positionOfStatus1Column = i + 1;
        }
        if (headers[i].innerHTML.indexOf('Status 2') != -1) {
            positionOfStatus2Column = i + 1;
        }
        if (headers[i].innerHTML.indexOf('Status 3') != -1) {
            positionOfStatus3Column = i + 1;
        }
    }

    // now that we know the positions of the Status columns, we can hide all the cells

    // make sure we found the column before trying to hide anything
    if (positionOfStatus1Column != null) {
        // only one header, so we can use querySelector
        document.querySelector('.ms-listviewtable th:nth-child(' + positionOfStatus1Column + ')').style.display = 'none';

        // have to get all the regular td cells, so we have to use querySelectorAll
        document.querySelectorAll('.ms-listviewtable td:nth-child(' + positionOfStatus1Column + ')').forEach(function (cell) {
            cell.style.display = 'none';
        });
    }
    if (positionOfStatus2Column != null) {
        document.querySelector('.ms-listviewtable th:nth-child(' + positionOfStatus2Column + ')').style.display = 'none';
        document.querySelectorAll('.ms-listviewtable td:nth-child(' + positionOfStatus2Column + ')').forEach(function (cell) {
            cell.style.display = 'none';
        });
    }
    if (positionOfStatus3Column != null) {
        document.querySelector('.ms-listviewtable th:nth-child(' + positionOfStatus3Column + ')').style.display = 'none';
        document.querySelectorAll('.ms-listviewtable td:nth-child(' + positionOfStatus3Column + ')').forEach(function (cell) {
            cell.style.display = 'none';
        });
    }
}
4
  • Though, one small concern, what if the last child column is NOT the only one column I want to hide. What if I have 8 more status columns to hide ? Do I have to write it as a new question ? Feb 5, 2018 at 22:11
  • No, I will update my answer later this evening to address hiding multiple columns. Feb 5, 2018 at 22:14
  • @ParinitaHirehal updated my answer. Feb 6, 2018 at 17:02
  • This works just fine.... :) Thank you much @DylanCristy Feb 6, 2018 at 21:10
3

to hide one column , in the below script will hide cloumn named Status

<script>
function hideColumn()
{ 
     var header = document.querySelectorAll("[displayname="Status"]")[0].parentNode;
    var index = [].slice.call(header.parentNode.children).indexOf(header) + 1;
    header.style.display = "none";
    for (var i = 0, cells = document.querySelectorAll("td:nth-child(" + index + ")"); i < cells.length; i++) {
        cells[i].style.display = "none";}

}
_spBodyOnLoadFunctionNames.push('hideColumn');
</script>

to hide multiple columns , use the below script replace col1, col2,col3 , with your columns names

<script>
function hideColumns()
{ 
  ["col1", "col2","col3"].forEach(function(col) {
    var header = document.querySelectorAll("[displayname='"+ col +"']")[0].parentNode; //Recommend wrapping displayname value with an apostrophe ' to handle column names containing spaces.
    var index = [].slice.call(header.parentNode.children).indexOf(header) + 1;
    header.style.display = "none";
    for (var i = 0, cells = document.querySelectorAll("td:nth-child(" + index + ")"); i < cells.length; i++) {
        cells[i].style.display = "none";}
    });
}
_spBodyOnLoadFunctionNames.push('hideColumns');
</script>
6
  • 1
    This approach will not help here. The problem is that the OP is using the values of the "Status" column to do conditional formatting using CSR in a list view, therefore the "Status" column must be included in the view, or you won't have access to the data. However, OP does not actually want the "Status" column to be seen in the view. Feb 5, 2018 at 19:59
  • @DylanCristy thanks for the clarification, i edited my answer to match with the mentioned case,
    – A.Saéed
    Feb 6, 2018 at 10:56
  • @Ahmed Saeed, I just tried it and it is working flawlessly. Thank you. Feb 6, 2018 at 14:35
  • @ParinitaHirehal welcome, glad to help
    – A.Saéed
    Feb 7, 2018 at 10:06
  • THANK YOU!!! This worked well for me. I added 1 suggestion to wrap the displayname value with an apostrophe (') to handle column names containing spaces.
    – ashdiggedy
    Mar 7, 2019 at 2:31
0

I think you should hide the column with javascript after changing the color. Best bet would be to select the tr and th based on their columns numeric value. Examples below:

$('table[summary="Shared Documents"] th')[1].hide();
$('table[summary="Shared Documents"] tbody tr').each(function() {
    $(this).children()[2].hide();
})

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.