Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Datatable: with columnToggler displays wrong headerText when header has a Link/Button #9647

Closed
edudoda opened this issue Jan 12, 2023 · 13 comments · Fixed by #9655
Closed

Datatable: with columnToggler displays wrong headerText when header has a Link/Button #9647

edudoda opened this issue Jan 12, 2023 · 13 comments · Fixed by #9655
Assignees
Labels
🐞 defect Bug...Something isn't working workaround A workaround has been provided
Milestone

Comments

@edudoda
Copy link

edudoda commented Jan 12, 2023

Describe the bug

I have some datatable columns with links/buttons specified like:

 <p:column    >
	       <f:facet name="header">
		        <h:outputText value="myHeader"  />   
			  <p:commandLink     action="#{myBean.xpto}"       >									 
					     <i class=" fa fa-pie-chart icon-black"/> 
			    </p:commandLink>  
          </f:facet>						             						 
		   <h:outputText value="#{item.test}"  />  
   </p:column>

And a component columnToggler to select which columns need to be showed:
<p:columnToggler datasource="tabelaItens" trigger="togglerColTab" />

Each column that has <p:commandLink /> or <p:commandButton /> (this one is also worse because it displays the title="" value as well) displays a code like:

myHeader  $(function(){PrimeFaces.cw("CommandLink","widget_formDetalhe_tabelaItens_j_idt371", 
     {id:"formDetalhe:tabelaItens:j_idt371"});}     

on columnToggler near the column name. Even if insert <p:column headerText="myHeader" ...> error persist.

Reproducer

https://github.com/edudoda/primefaces-test-cases

Expected behavior

Only column header (text) should be displayed on <p:columnToggler />, especially when headerText is specified.

PrimeFaces edition

Elite

PrimeFaces version

12.0.2

Theme

No response

JSF implementation

All

JSF version

2.2

Java version

8

Browser(s)

No response

@edudoda edudoda added ‼️ needs-triage Issue needs triaging 🐞 defect Bug...Something isn't working labels Jan 12, 2023
@melloware
Copy link
Member

Working fine for me.

image

image

Please provide an executable example using the PrimeFaces Test project. It is the only way developers can debug your problem to help.

@melloware melloware added Resolution: Cannot Replicate Issue could not be reproduced by core devs Status: Needs Reproducer Needs a reproducer showing the issue and removed 🐞 defect Bug...Something isn't working ‼️ needs-triage Issue needs triaging labels Jan 12, 2023
@edudoda
Copy link
Author

edudoda commented Jan 12, 2023

Your example doesn't have any btn or link component next to header text.

image

@melloware
Copy link
Member

I copied your example above exactly?

@melloware
Copy link
Member

Code:

<p:column>
	<f:facet name="header">
		<h:outputText value="myHeader" />
		<p:commandLink action="#{buttonView.save}">
			<i class="pi pi-check" />
		</p:commandLink>
	</f:facet>

	<h:outputText value="#{product.name}" />
</p:column>

Output:
image

@edudoda
Copy link
Author

edudoda commented Jan 12, 2023

Ok, a reproducer was attached now.
Thanks you for your help @melloware

@melloware
Copy link
Member

OK now I know why I couldn't reproduce it. Simple fix for you right now that will fix this AND make your web pages load MUCH faster. Add this to web.xml

    <context-param>
        <param-name>primefaces.MOVE_SCRIPTS_TO_BOTTOM</param-name>
        <param-value>true</param-value>
    </context-param>

@melloware melloware added 🐞 defect Bug...Something isn't working workaround A workaround has been provided and removed Resolution: Cannot Replicate Issue could not be reproduced by core devs Status: Needs Reproducer Needs a reproducer showing the issue labels Jan 12, 2023
@melloware
Copy link
Member

melloware commented Jan 12, 2023

So what is happening is that PF just grabs the Column Header and call jQuery text() on it to get the text version of the node. Scripts apparently still get presented in that text string.

            columnChildren = column.children('.ui-column-title'),
            columnTitle = columnChildren.text(),

@melloware
Copy link
Member

MonkeyPatch:

if (PrimeFaces.widget.ColumnToggler) {
    PrimeFaces.widget.ColumnToggler.prototype.render = function() {
        this.columns = this.thead.find('> tr > th:not(.ui-static-column)');
        this.panel = $(PrimeFaces.escapeClientId(this.cfg.id)).attr('role', 'dialog').addClass('ui-columntoggler ui-widget ui-widget-content ui-shadow ui-corner-all')
                .append('<ul class="ui-columntoggler-items" role="group"></ul>').appendTo(document.body);
        this.itemContainer = this.panel.children('ul');

        var stateHolderId = this.tableId + "_columnTogglerState";
        this.togglerStateHolder = $('<input type="hidden" id="' + stateHolderId + '" name="' + stateHolderId + '" autocomplete="off"></input>');
        this.table.append(this.togglerStateHolder);
        this.togglerState = [];

        //items
        for(var i = 0; i < this.columns.length; i++) {
            var column = this.columns.eq(i),
            hidden = column.hasClass('ui-helper-hidden'),
            boxClass = hidden ? 'ui-chkbox-box ui-widget ui-corner-all ui-state-default' : 'ui-chkbox-box ui-widget ui-corner-all ui-state-default ui-state-active',
            iconClass = (hidden) ? 'ui-chkbox-icon ui-icon ui-icon-blank' : 'ui-chkbox-icon ui-icon ui-icon-check',
            columnChildren = column.children('.ui-column-title').clone(),
            columnTogglerCheckboxId = this.tableId + "_columnTogglerChkbx" + i;
            columnChildren.children().remove('script'); // GitHub #9647 remove scripts
            var columnTitle = columnChildren.text();

            var label = columnChildren.find('label');
            if (label.length) {
                columnTitle = label.text();
            }

            this.hasPriorityColumns = column.is('[class*="ui-column-p-"]');

            var item = $('<li class="ui-columntoggler-item">' +
                    '<div class="ui-chkbox ui-widget">' +
                    '<div role="checkbox" tabindex="0" aria-checked="'+ !hidden + '" aria-labelledby="'+ columnTogglerCheckboxId + '" class="' + boxClass + '">' +
                    '<span class="' + iconClass + '"></span></div></div>' +
                    '<label id="' + columnTogglerCheckboxId + '">' + PrimeFaces.escapeHTML(columnTitle) + '</label></li>').data('column', column.attr('id'));

            if(this.hasPriorityColumns) {
                var columnClasses = column.attr('class').split(' ');
                for(var j = 0; j < columnClasses.length; j++) {
                    var columnClass = columnClasses[j],
                    pindex = columnClass.indexOf('ui-column-p-');
                    if(pindex !== -1) {
                        item.addClass(columnClass.substring(pindex , pindex + 13));
                    }
                }
            }

            item.appendTo(this.itemContainer);

            this.togglerState.push(column.attr('id') + '_' + !hidden);
        }

        this.togglerStateHolder.val(this.togglerState.join(','));

        //close icon
        this.closer = $('<a href="#" class="ui-columntoggler-close"><span class="ui-icon ui-icon-close"></span></a>')
                .attr('aria-label', PrimeFaces.getAriaLabel('columntoggler.CLOSE')).prependTo(this.panel);

        if(this.panel.outerHeight() > 200) {
            this.panel.height(200);
        }
        this.hide();
    }
}

@edudoda
Copy link
Author

edudoda commented Jan 13, 2023

OK now I know why I couldn't reproduce it. Simple fix for you right now that will fix this AND make your web pages load MUCH faster. Add this to web.xml

    <context-param>
        <param-name>primefaces.MOVE_SCRIPTS_TO_BOTTOM</param-name>
        <param-value>true</param-value>
    </context-param>

Hi there @melloware , after doing that solved that problem but now I start to receive javascript errors in pages that have multiples <h:form/> (like pages with some modal pages inside). Apparently, this erros affects only Primefaces components, like <p:selectOneMenu/> or <p:calendar/> (<h:selectOneMenu/> are not affected for example). Do you have any clue about it?

image

@melloware
Copy link
Member

I have multiple h:form's too, you don't have Nested Forms do you? I have a feeling the issue is Calendar not SelectOne since that is the error above. If you don't feel like debugging set MOVE_SCRIPTS back to false and use the MonkeyPatch i provided above.

@edudoda
Copy link
Author

edudoda commented Jan 13, 2023

Digging a little bit more, I could notice that in fact it is not (just) <form /> related but something with <ui:include />, when I use it inside the main/first form it works fine, but if I use any <ui:include /> outside main form or in another (not nested) <form/> the error appear. If I just copy and paste the content page included directly it also works. Btw it happens with both components, just printed an example with both simultaneously.
Your patch/correction will be in 12.0.3?

@melloware
Copy link
Member

No it will only be in 12.0.3 if you request it through your PRO account to have it added to the Elite release. I would just add the script above into your application and it will work.

@edudoda
Copy link
Author

edudoda commented Jan 13, 2023

I just created a new issue related to MOVE_SCRIPTS_TO_BOTTOM param with a reproducer: #9673

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
🐞 defect Bug...Something isn't working workaround A workaround has been provided
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants