Add or Append text in p:textEditor - jsf

I have p:textEditor like the following
<p:textEditor
id="editor"
widgetVar="editor"
value="#{xxxController.editorText}"
height="300"
placeholder="Enter your content"
toolbarVisible="false"/>
Have the following command button to add/append values to p:textEditor
<p:commandButton onclick="insertTag('[myValue]')" value="myValue" type="button" />
JavaScript
<script>
function insertTag( t )
{
PF( 'editor' ).insertText( t ) ;
}
</script>
But i get SCRIPT5007: Unable to get property 'insertText' of undefined or null reference when i try to click the <p:commandButton.
So how do we insert/append text using widgetVar or JavaScript to p:textEditor?
Version details
JSF 2.2,
PrimeFaces 6.2

You need to do this... Once you have the widget the "editor" variable is QuillJS object.
PF('editor').editor.insertText(0, 'Hello', 'bold', true);
See: https://quilljs.com/docs/api/#inserttext
See: https://quilljs.com/docs/api/#getlength

See Using the component ID as widgetVar name
[...] This will cause all original widget var functions to be completely unavailable because the variable editor is now referencing a HTMLDivElement instance which doesn't have the same functions as the original widget var like show(), etc. [...]
(Append a _vw to every widgetvar name, to eliminate that issue)
SCRIPT5007: Unable to get property 'insertText' of undefined or null reference
guess, that's exactly the cause, your code is not referencing the "editor"-widgetVar, but the "editor" html element, which does not know "insertText".

Related

Primefaces NotificationBar close icon not visible

In the documentation of primefaces, it is said that "Note that notificationBar has a default built-in close icon to hide the content.". But so far I could not get it displayed ? Is there a special property or facet required to show the close icon ?
pf version I am using is 6.2
If you see the notification.js resource inside the Primefaces library, you can see that they took into account to give to the close icon the "hide functionality":
primefaces-6_2\src\main\resources\META-INF\resources\primefaces\notificationbar\notificationbar.js =>
/**
* PrimeFaces NotificationBar Widget
*/
PrimeFaces.widget.NotificationBar = PrimeFaces.widget.BaseWidget.extend({
init: function(cfg) {
this._super(cfg);
var _self = this;
//relocate
this.jq.css(this.cfg.position, '0').appendTo($('body'));
//display initially
if(this.cfg.autoDisplay) {
$(this.jq).css('display','block')
}
//bind events
this.jq.children('.ui-notificationbar-close').click(function() {
_self.hide();
});
},
So, considering the previous code, if a children component has the ui-notificationbar-close class and you click on it, the NotificationBar component will be hided calling to hide function automatically (without having to use the PF(widgetVar).hide().
I have tested with the following code and in effect, the notificationbar disappears after clicking on the close icon:
<p:notificationBar id="notificationBar" position="top" effect="slide" styleClass="top" widgetVar="myNotificationBarWV" autoDisplay="false">
<i class="ui-icon ui-icon-closethick ui-notificationbar-close"></i>
<h:outputText value="You Rock!" style="font-size:1.5 rem;"/>
</p:notificationBar>

JSF PrimeFaces rendering components

Let's say I have a simple method that, like this:
public String test()
{
return "hello";
}
Now let's say I have the following PrimeFace component:
<p:fieldset styleClass="containers" rendered="#{controller.test()}">
<h2>Testing</h2>
<p:outputLabel for="test" value="Test" />
<p:inputText id="test" />
</p:fieldset>
The method above returns "hello". I would like to dynamically show and hide that fieldSet by comparing the returned value of that method to a field of one of my beans. For instance, on the rendered parameter, I would like to do something like: controller.test() != "some variable" which would return true or false. Am I allow to do that? If not, what is the way of doing it?
Basically the goal is to dynamically show and hide some container by comparing the returned value of a method with a bean property.
Look Like you misunderstood rendered
The rendered Attribute
A component tag uses a Boolean EL expression, along with the rendered
attribute, to determine whether or not the component will be rendered.
If you will check above definition you will know what exactly is the use of this attribute.
More you can see below
The rendered attribute which uses Boolean EL expression indicates
whether a component is currently visible or not. The property is
useful when you want to hide components for specific users or based on
condition. The default value of rendered attribute is true.
<h:outputText value=”mapping” rendered=”Boolean EL expression” />
For example, the commandLink component in the following section of a page is not rendered if the cart contains no items:
<h:commandLink id="check"
...
rendered="#{cart.numberOfItems > 0}">
<h:outputText
value="#{bundle.CartCheck}"/>
</h:commandLink>
With your concrete problem you can do like this
Make a String variable call value
Now create get/set methods for above variable
Now in your test method you can add
public void test(){
value="hello";
}
Bur remember you have call test() method of page load
Now in your Xhtml or Jsf or Jsp page
rendered="#{controller.value != 'hello'}"
Or better way create a Boolean variable and do all the magic of hide and show the component

p:remoteCommand returns <eval> twice in ajax response

I try to render a new page in a new window (or tab) with the link I get from a selected page object in an autoComplete component.
After trying multiple options the only chance in my opinion is to use javascript to catch the submit, trigger a remote command, that gives me a javascript call with the link attribute from the page object.
JSF-Snipplet (with reduced attributes in autoComplete)
<h:form id="autoCompleteForm">
<p:autoComplete id="autoComplete" widgetVar="autoCompleteWidget" value="#{pageBean.selectedPage}" />
<p:remoteCommand action="#{pageBean.showPage}" name="showPage" />
</h:form>
some JS:
// form submit
('#autoCompleteForm').on('submit', function(e) {
e.preventDefault();
showPage();
});
// open link
var openLink = function(pageLink) {
window.open(pageLink, '_blank');
};
Bean part for action
public void showPage() {
RequestContext context = RequestContext.getCurrentInstance();
context.execute("openLink('" + selectedPage.getLink() + ".xhtml')");
}
Everything works nice together, but the response contains the eval tag twice.
<partial-response>
<changes>
<update id="javax.faces.ViewState"><![CDATA[2851816213645347690:-2276123702509360418]]></update>
<eval><![CDATA[openLink('target.xhtml');]]></eval>
<eval><![CDATA[openLink('target.xhtml');]]></eval>
</changes>
</partial-response>
I tried different approaches with redirects or returning view names, but that all leads to no satisfying solutions (e.g. URL not changing or no new window).
Problem solved:
I had defined PrimePartialViewContextFactoryin my faces-config before:
<factory>
<partial-view-context-factory>org.primefaces.context.PrimePartialViewContextFactory</partial-view-context-factory>
</factory>
By removing it the application acts like expected.
This also solves a problem (JSON.parse: unexpected non-whitespace character after JSON data) with pagination and sorting in DataTables.

Render JSF h:message with p element instead of span

I would like to create a custom message renderer to renders h:message as a 'p' html element instead of as a 'span' element. It concerns the following message tag:
<h:message id="firstNameErrorMsg" for="firstname" class="error-msg" />
I've written to code underneath, but that's only rendering an empty 'p' element. I suppose I have to copy all attributes and text from the original component and write it to the writer. However, I don't know where to find everything and it seems to be a lot of work for just a replacement of a tag.
Is there a better way to get an h:message tag rendered as a 'p' element?
Code:
#FacesRenderer(componentFamily = "javax.faces.Message", rendererType = "javax.faces.Message")
public class FoutmeldingRenderer extends Renderer {
#Override
public void encodeEnd(final FacesContext context, final UIComponent component) throws IOException {
ResponseWriter writer = context.getResponseWriter();
writer.startElement("p", component);
writer.endElement("p");
}
}
It isn't exactly "a lot of work". It's basically a matter of extending from the standard JSF messages renderer, copypasting its encodeEnd() method consisting about 200 lines then editing only 2 lines to replace "span" by "p". It's doable in less than a minute.
But yes, I agree that this is a plain ugly approach.
You can consider the following alternatives which are not necessarily more easy, but at least more clean:
First of all, what's the semantic value of using a <p> instead of a <span> in this specific case? To be honest, I'm not seeing any semantic value for this. So, I suggest to just keep it a <span>. If the sole functional requirement is to let it appear like a <p>, then just throw in some CSS. E.g.
.error-msg {
display: block;
margin: 1em 0;
}
You can obtain all messages for a particular client ID directly in EL as follows, assuming that the parent form has the ID formId:
#{facesContext.getMessageList('formId:firstName')}
So, to print the summary and detail of the first message, just do:
<c:set var="message" value="#{facesContext.getMessageList('formId:firstName')[0]}" />
<p title="#{message.detail}">#{message.summary}</p>
You can always hide it away into a custom tag file like so:
<my:message id="firstNameErrorMsg" for="firstname" class="error-msg" />
Use OmniFaces <o:messages>. When the var attribute is specified, then you can use it like an <ui:repeat>.
<o:messages for="firstNameErrorMsg" var="message">
<p title="#{message.detail}">#{message.summary}</p>
</o:messages>

calling a Javascript function that makes a click on a (hidden) button or link

I call a javascript function that makes a click on a hidden commandButton but the click run when the page loads, not when I call the function.
this is the html code :
<p:inputText id="aa" value="#{bonBonneManagedBean.sel}" onkeyup="fnc()" />
<h:commandButton id="hh" onclick="#{bonBonneManagedBean.kk()}" style="display:none"/>
and the javaScript function :
function fnc()
{
length = document.getElementById('form:aa').value.length;
if(length == 10)
{
$("#hh").click();
document.getElementById('form:aa').value = "";
}
}
You should use the action attribute instead of onclick like this
<h:commandButton id="hh" action="#{bonBonneManagedBean.kk()}" style="display:none"/>
Note that you might have to add form prefix to the selector, like this
$("#myFormId\\:hh").click();
The same would work for a commandLink or any other 'clickable' component.
Must there be a button on this page(which I doubt, seeing as you're hiding it anyways)? You're better served using something like <p:remoteCommand/> here
Ditch the hidden button and replace with
<p:remoteCommand name="fnc" actionListener="#{bonBonneManagedBean.kk}"/>
But, if it's an absolute requirement, you can very easily emulate a button click in js with the click() method from your function you need to
Change the <h:commandButton/> to a <p:commandButton/> so you can assign the button a widgetVar attribute(to guarantee the name of the element in the DOM). The widgtetVar attribute can be set on almost all primefaces components to make your life easier
Using the widgetVar, just call the click() method in your function
<p:commandButton ajax="false" widgetVar="theButton" id="hh" action="#{bonBonneManagedBean.kk()}" style="display:none"/>
<p:inputText id="aa" widgetVar="theTextBox" value="#{bonBonneManagedBean.sel}" onkeyup="fnc()" />
and in the function:
function fnc(){
length = theTextBox.value.length;
if(length == 10){
theButton.click()
theTextBox.value = "";
}
}
If the top answers from Daniel and Kolossus doesn't help out someone: I found that characters got put in front of the id I set in my case, therefore this helped me:
$('[id$=hh]').click();
Basically the selector is saying the id ends with 'hh' but may not be the full id.
This is also helpful in SF development as the same thing happens with comandButtons, etc.

Resources