Programmatically include xhtml fragment in MyFaces - facelets

I know it is possible in MyFaces to programmatically add a xhtml fragment to the component tree, instead of using ui:include.
The snipplet I am talking about is as (in the original form):
ViewDeclarationLanguage vdl = facesContext.getApplication().getViewHandler().getViewDeclarationLanguage(facesContext, facesContext.getViewRoot().getViewId());
Map<String, Object> attributes = new HashMap<String, Object>();
attributes.put("src", "/fragmentToInclude.xhtml");
UIComponent component = vdl.createComponent(facesContext, "http://java.sun.com/jsf/facelets", "include", attributes);
The problem I am facing is I am not able to pass in parameters, that would normally be passed in via <ui:param .../> tag.
What I tried, of course, was to add params into attributes map:
attributes.put("testingParam1", "Yeah, it worked!");
But this seems not to help. Content of my testing fragment is quite simple:
<ui:composition xmlns:ui="http://xmlns.jcp.org/jsf/facelets">
<div class="testingDiv">#{empty testingParam1 ? 'testingParam1 IS EMPTY' : testingParam1}</div>
</ui:composition>
The fragment is properly loaded, but I only get that 'is empty' message.
I have walked through multiple resources but haven't found answer there:
NullPointerException in MyFaces facelet inclusion
http://lu4242.blogspot.cz/2014/01/whats-new-in-myfaces-22.html
https://java.net/projects/javaserverfaces-spec-public/lists/jsr344-experts/archive/2014-03/message/12
https://java.net/projects/javaserverfaces-spec-public/lists/users/archive/2014-10/message/120
Please, do you know, is this even possible? Or am I missing something? Thanks for any hints.

Related

How to access Another Module's Content and Presentation Items after 2sxc v10.20+

Here is code that worked up through 2sxc 10.9.1. Though I am able to get the CmsBlock for the TabID, ModuleID and get that to .Render(), I need more. Here is the old code. Not sure it makes any difference, but this View is using the normal Link content-type and is running in an older version of the Content App (appx 3.03=ish). 2sxc has been upgraded and is now 11.22.0 LTS.
I have removed unnecessary stuff, so I doubt this runs as is...
#using ToSic.Razor.Blade
#using ToSic.SexyContent.Environment.Dnn7
#{
var Helpers = CreateInstance("_Helpers.cshtml");
// Display the items from the Manage Links module, we go in 'sideways'
// this gives us just the Content items with their Presentations settings, etc.
var sxci = Factory.SxcInstanceForModule(3360, 606); // ModuleID of Manage Links
var dyn = Factory.CodingHelpers(sxci);
var allLinks = dyn.AsDynamic(dyn.Data["Default"]);
}
#* other stuff *#
<div class="row co-documents justify-content-center align-items-center">
#foreach (var linkItem in allLinks) {
var linkInfo = Helpers.LinkInfos(linkItem.Link, linkItem.Window, linkItem.Icon);
string iconStyle = linkItem.IconStyle ?? "fas";
int linkColumns = (int)linkItem.Presentation.Columns;
string linkIconAlign = linkItem.Presentation.IconAlign;
string linkIconBGColor = linkItem.Presentation.IconBGColor;
#* other stuff *#
}
</div>
So the easy thing to figure out was how to get the module as a CmsBlock which I can Render() as is (below), but what I need to do instead is get proper access to the List of Content Items AND their Presentation data (like above, allLinks).
ToSic.Sxc.Dnn.Factory.CmsBlock(606, 3360).Render();
What am I missing? How can I get access to the other module's data like I was doing before? In this case, I do this in 3 different places on the website. So to outline this in English, I have a module that the client manages a few special links that get displayed in MegaMenus, other special nav, and directly on a couple of pages. In each place they render differently. In their "home" module, where they get edited, they just look boring like this:
I realize its something like this:
var allLinks = something1.AsList(something2.Data["Default"]);
I understand that something2 is an app instance, but how do I create it in the context of the other module?
And what is something1 nowadays? And how do instantiate it? Looks like its a new ToSic.Sxc.Code.DynamicCode() but I can't figure out how to construct that in a way that I can use or doesn't just throw errors.
Thanks in advance for any insight!!
Okay, it took a little testing, trial and error. And also I missed that DynamicCode() was a Method of the Factory class. In retrospect it does seem easy now.
So first you get the BlockBuilder
var block = Factory.CmsBlock(606, 3360);
Then you get the DynamicCode instance (Code.DnnDynamicCodeRoot) from that
var dc = Factory.DynamicCode(block);
And then things are normal
var allLinks = AsList(dc.Data["Default"]);
The rest of the code works like it did before; I can foreach through the links with Header (renamed from ListContent) and Presentation (now Content.Presentation) working just as expected.
The above answer works fine if you are inside the C# Razor template of the 2sxc View. But what if you are outside, for example in a Razor template for a DDR Menu?
Same two steps as above (get the block and the dc), but then you do NOT have access to AsList() or the App. Thankfully, you already have DynamicCode, so you could just get all the records in the Bibliography content-type like this:
<ul>
var items = dc.AsList(dc.App.Data["Bibliography"]);
foreach (var item in items)
{
<li>#item.EntityTitle</li>
}
</ul>
So once you've got your dc you've got access to all the usual 2sxc toys.

Angular Request how it works for nestjsx/crud

I've been trying for hours to make it work and I can't do it, I hope some of you have the answer to my question because it must be very simple and I am a beginner
I am using AngularJs and NestJs in Nest used the #nestjsx/crud and I went trow the request docs so, here is the problem:
This is my Angular service function
getProductsOfPiece(pieceId: number): Observable<ProductSimple[]> {
return this.http.get<ProductSimple[]>(
'api/producto/', {
params: {
fields: "id,refFabr,refCliente,descrCorta,imagen",
filter: 'pieza.id||$eq||'+ pieceId
}
}
);
}
This request gives me a 400 Bad Request, it looks like this:
/api/producto/?fields=id,refFabr,refCliente,descrCorta,imagen&filter=pieza.id%257C%257C$eq%257C%257C1
I imagine the % and the hexadecimal have something to do with the URI coding and tried to encode/decode it, but didn't work.
I also tried using the class RequestQueryBuilder of #nestjsx/crud-request from the FrontEnd usage referenced in the docs, and append it to the URL
let queryString = RequestQueryBuilder.create()
.select(["id","refFabr","refCliente","descrCorta","imagen"])
.setFilter({
field: "coleccion.id",
operator: CondOperator.EQUALS,
value: collectionId
}).query();
return this.http.get<ProductSimple[]>(
'api/producto/?'+queryString
);
but got worse result
/api/producto/?fields=id%2CrefFabr%2CrefCliente%2CdescrCorta%2Cimagen&filter%5B0%5D=pieza.id%7C%7C%24eq%7C%7C1
What I don't understand is how I do this with my Postmand and it works!
api/producto/?fields=id,refFabr,refCliente,descrCorta,imagen&filter=coleccion.id||$eq||6
How can I make it work, what is wrong with my code?
Finally got the answer, just had to set the .query(false) on the RequestQueryBuilder, this boolean parameter is for encode, seams like Angular's HttpClient class does some encoding or something to the URL so, anyway
It Works! Here is the code:
getProductsOfPiece(pieceId: number): Observable<ProductSimple[]> {
let queryString = RequestQueryBuilder.create()
.select(["id","refFabr","refCliente","descrCorta","imagen"])
.setFilter({
field: "coleccion.id",
operator: CondOperator.EQUALS,
value: collectionId
}).query(false);
return this.http.get<ProductSimple[]>(
'api/producto/?'+queryString
);
}
And you need to import
RequestQueryBuilder of #nestjsx/crud-request
npm i #nestjsx/crud-request.
Any observations are welcome...
UPDATE
To create or update
Here are de docs
Create One https://github.com/nestjsx/crud/wiki/Controllers#create-one-resource
Update One https://github.com/nestjsx/crud/wiki/Controllers#update-one-resource
Following that guide the create and update are simple
Just do POST to the API 'api/producto/' (for example) with the object as body in the request
For the Update follows similar just using the PUT method and the API with the model id 'api/producto/1' (for example)

Inserting image into visualforce email template (without hard-coding IDs)

The "official" solution for including images in visualforce email templates suggests hard coding IDs in your template to reference an image file stored as a document.
https://help.salesforce.com/HTViewHelpDoc?id=email_template_images.htm&language=en_US
Is there a better way that avoids hard coding instance ID and OID? I tried using the partner URL to grab the instance ID, but I got the following error
Error Error: The reference to entity "oid" must end with the ';' delimiter.
Using:
{!LEFT($Api.Partner_Server_URL_140,FIND(".com/",$Api.Partner_Server_URL_140)+3)/
to replace "https://na2.salesforce.com/"
in
"na2.salesforce.com/servlet/servlet.ImageServer?id=01540000000RVOe&oid=00Dxxxxxxxxx&lastMod=1233217920"
Should I use a static resource instead?
I've arrived here looking for an answer for this question related to hardcoded ID and OID in Visualforce e-mail templates. Well, I found a workaround for that.
First I needed to create a Visualforce Component:
<apex:component access="global" controller="LogomarcaController">
<apex:image url="{!LogoUrl}" />
</apex:component>
In the respective controller class, I've created a SFInstance property to get the correct URL Salesforce Instance, LogoUrl property to concatenate SFInstance and IDs... And Finally I've used Custom Settings (Config_Gerais__c.getInstance().ID_Documento_Logomarca__c) to configurate the ID of Image (in my case, Document Object) on Sandbox or Production:
public class LogomarcaController {
public String LogoUrl {
get {
id orgId = UserInfo.getOrganizationId();
String idDocumentoLogomarca = Config_Gerais__c.getInstance().ID_Documento_Logomarca__c;
return this.SfInstance + '/servlet/servlet.ImageServer?id=' + idDocumentoLogomarca + '&oid=' + orgId ;
}
}
public String SfInstance
{
get{
string SFInstance = URL.getSalesforceBaseUrl().toExternalForm();
list<string> Dividido = SFInstance.split('.visual', 0);//retira o restante a partir de .visual
SFInstance = dividido[0];
dividido = SFInstance.split('://',0);//retira o https://
SFInstance = dividido[1];
if(!SFInstance.contains('sybf')) //managed package prefix, if you need
{
SFInstance = 'sybf.'+ SFInstance;
}
return 'https://'+SFInstance;
}
}
}
And finally, I've added the component in Visualforce template:
<messaging:emailTemplate subject="Novo OfĂ­cio - {!relatedTo.name}" recipientType="User" relatedToType="Oficio__c" >
<messaging:htmlEmailBody >
<c:Logomarca />
</messaging:htmlEmailBody>
<messaging:plainTextEmailBody >
</messaging:plainTextEmailBody>
</messaging:emailTemplate>
PS: Some of my variables, properties and comments are in my native language (portuguese). If you have some problems understanding them, please ask me!
We ran into a similar problem and after trying various solutions, the following worked for us. In our case the image is uploaded as a content asset(https://help.salesforce.com/articleView?id=000320130&type=1&language=en_US&mode=1)
Solution:
<img src="{!LEFT($Api.Partner_Server_URL_260,FIND('/services',$Api.Partner_Server_URL_260))}/file-asset-public/<Image_Name_Here>?oid={!$Organization.Id}&height=50&width=50"/>

Entity images + Blobstore

I'm quite confused about how the Blobstore works alongside serving images per entity.
So let's say I have:
class Book(ndb.Model):
title = ndb.StringProperty()
cover_image = ndb.BlobProperty()
How can I output this information in a jinja2 template, like this:
<h1>{{title}}</h1>
{{cover_image}}
My confusion stems from my being unclear about how the Blobstore and the datastore works together. For example: How do we relate a datastore's entity to a Blobstore property (in our example, it would be relating the the cover_image blobproperty to its Book entity)?
A simplified explanation would be much appreciated. Thank you.
What you are looking for is get_serving_url(blob_key, size=None, crop=False, secure_url=None)
Try this method on the blob and you will get an image url.
Docs
You upload the blob and you get a blobkey that you store. Imagine it like another entity's key.
Then having that key you use the get_serving url and several other functions in order to serve a url, resize etc.
You can just use a BlobKeyProperty in your model to maintain a reference between the datastore and the blobstore. For example:
class MyContent (ndb.Model):
Image = ndb.BlobKeyProperty()
Then, if you need to frequently get the associated URL you can even also store the serving URL:
class MyContent (ndb.Model):
Image = ndb.BlobKeyProperty()
ImageServingURL = ndb.StringProperty()
You can create a different handler for getting the images. The way you do that depends on the framework used. Pyramid example (without try and excepts):
#handler /{bookid}/coverimage
def RenderImage(request):
book_key = request.matchdict['bookid']
book = Key(urlsafe=book_key}.get()
cover = book.cover_image
#optional rezising:
cover = images.resize(cover, WIDTH, HEIGHT) #or other image operations
response = Response(content_type="image/jpeg")
response.body = cover
return response
In your template:
<img src="/{{book.key.urlsafe()}}/coverimage" />
Note: you can do a generic image handler for any image property, not only 'cover_image'

ADF - Unable to read view Id of Declarative Component from "var" of af:iterator

I am facing a weird issue where when i assign "var" of af:iterator to the view Id of declarative component, it is saying " Encountered null from the viewId expression: #{row}"
And Page is showing blank.
My JSPX code is as follows :
<af:iterator value="#{pageFlowScope.stageBean.pathList}" var="row">
<af:outputText value="#{row}" id="ot1"/>
<af:declarativeComponent viewId="#{row}"/>
</af:iterator>
And code snippet for getter in Java bean is as follows:
public List<String> getPathList()
{
List<String> pathList = new ArrayList<String>();
pathList.add("/Test.jspx");
return pathList;
}
The weird thing here is output text is printing the path /Test.jspx but declarative component is not recognizing it. Its showing blank page and in logs, error says "Encountered null from the viewId expression: #{row}"
If i remove #{row} from viewId and manually give like viewId = "/Test.jspx" , its displaying the page correctly.
Can anyone please help me solve this issue?
Regards,
Rakesh.
I remember this issue from the Oracle forums and I am not sure declarative components can be stamped (which is how af:iterator lays out its children). Can you try af:forEach?
Frank

Resources