How to retrieve session values in Sightly/HTL? - aem

I am using Sightly/HTL as the templating language in my AEM project (AEM version 6.3). As Sightly provides a lot of context objects, two of them being : request backed by org.apache.sling.api.SlingHttpServletRequest and currentSession backed by javax.servlet.http.HttpSession, I am trying to access some session parameter values in my sightly file by doing something like below:
${request.session.attribute # mySessionAttribute}
or
${currentSession.attribute # mySessionAttribute}
but am not able to get that value. Does anybody has any idea about how to do it?

In HTL/Sightly you cannot call arbitrary methods with parameters, it's a limitation by design. Since the javax.servlet.http.HttpSession API does not expose attributes as a map you can't access them as ${currentSession.attributes['mySessionAttribute']} so you will need to be creative about it:
script.html
<sly data-sly-use.attr="${'attrib.js' # session=currentSession, name='mySessionAttribute'}">${attr.value}</sly>
attrib.js
use(function () {
return {
value: this.session.getAttribute(this.name)
};
});

You can not pass arguments to methods in HTL like this and I would not recommend doing it anyway.
One way to solve this issue is to use a Sling Model:
#Model(adaptables = SlingHttpServletRequest.class)
public SessionModel {
#ScriptVariable
private Session currentSession;
public String getMySessionAttribute() {
return this.currentSession.getAttribute("attributeName");
}
}
HTL:
<div data-sly-use.sessionModel="com.mypackage.SessionModel">
${sessionModel.mySessionAttribute}
</div>

Related

Access AEM component data as JSON within HTL (Sightly)

I have created a component the fields of which have been mapped to a sling model. To get the data of the sling as JSON I have enabled Sling exporter as shown in the code below -
#Model(adaptables = { Resource.class }, defaultInjectionStrategy = DefaultInjectionStrategy.OPTIONAL, resourceType = "XXX/components/content/XXX")
#Exporter(name = "jackson", extensions = "json")
public interface ProofPointsModel {
#Inject
List<ProofPointsList> getProofPoint();
#Model(adaptables = { Resource.class }, defaultInjectionStrategy = DefaultInjectionStrategy.OPTIONAL)
interface ProofPointsList {
#Inject
String getProofText();
#Inject
String getProofIcon();
}
}
This works perfectly and I am able to see the JSON data when hit the end point from my browser.
I want to render this entire json object in my component's HTL. Is there an elegant way of doing this? I dont want to create an additional request to retrieve this data.
Basically I want to call this sling exporter from within my component and render the json object as is.
Thanks
Unfortunately, HTL does not allow doing these "server-side includes". The workaround is to expose the JSON in a getJson method of your model: Get .model.json as String

Mass CRUD REST edit/update controller

I am trying to create a RESTful CRUD controller with a little but significant difference that might be in conflict with REST idea but anyway:
I am trying to mass edit items like so /photos/{photo}/edit where item id parameters are like /photos/0&2&7/edit
What is the proper way to establish that in Laravel 5.3?
Is there a way to use some method injections or at least to receive a collection of parameters in the controller method ?
public function edit($id) {
//.......
}
Appreciate your kind help, BR
Using Eloquent you can do whereIn, so you just need to explode the photo parameter so that all the ids are in an array:
public function edit($ids) {
$photo_ids = explode('&', $ids);
$images = Image::whereIn('id', $photo_ids)->get();
}
You can switch out statically accessing the Image model like I did in this example, you can just method inject or dependency inject the image model, let me know if you'd like assistance with dependency/method injection.
Hey i guess you are trying Model binding so you have to use like this
public function edit(Photo $photo) {
//.......
}
Your route should like this
Route::model('photos','App\Photo');
Route::resource('photos','PhotoController');
or you can try this way
your route and function like this
Route::resource('photos','PhotoController');
public function edit($id) {
$photo = Photo::findorFail($id);
}

ZF3: set terminal / render view without layout (Zend-Expressive)

I have installed the skelleton app from ZF3 'zend-expressive'. In the routing config I have configured a few routes. Some of these routes should return a response without the layout. In ZF2 I simply used the ViewModel on which you could call "setTerminal". But now the ViewModel is not directy available in the Action, as it is nested as private property of the ZendViewRenderer. I cannot figure out how I can set the terminal, so the output is rendered without layout.
I have tried various options in the routing configuration, such as adding keys 'terminal', 'terminate' and 'may_terminate' with value true. Also have tried to make a seperate Factory, but ended up with the same problem that I cannot reach the ViewModel.. It also did not work to make a seperate ViewModel in the Action, when I setTerminal on true, and pass the object as 2nd parameter in the 'render' method of the ZendViewRenderer object, it fails when passing 'renderModal' of the same object: "Cannot render; encountered a child marked terminal"..
There must be a simple configuration that I am overlooking, so my question is. Does anyone know how I can set the view on terminal?
Hope that I explained my problem well. Many thanks in advance.
My solution!
Yes! I found a "solution". Instead of pushing into terminal setting of the ViewModal, I have implemented a new layout called "layout/terminal". This layout only outputs the variable $content. Reference: https://github.com/zendframework/zend-expressive/issues/360
To use this layout you should add a new Factory into the configuration.
<?php
namespace Factory;
use Interop\Container\ContainerInterface;
use Zend\Expressive\Template\TemplateRendererInterface;
use Zend\ServiceManager\Factory\FactoryInterface;
use Zend\View\Model\ViewModel;
class RenderWithoutTemplate implements FactoryInterface
{
public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
{
$template = $container->has(TemplateRendererInterface::class)
? $container->get(TemplateRendererInterface::class)
: null;
$r = new \ReflectionClass($template);
$view = new ViewModel();
$view->setTerminal(true); // Does not affect any render behaviour (?)
$view->setTemplate('layout/terminal');
$prop = $r->getProperty('layout');
$prop->setAccessible(true);
$prop->setValue($template, $view);
return $template;
}
}
public function indexAction(){
return $this->getResponse();
}

TYPO3 extension "news": Custom fields on Fluid Template

I am using the extension News System, "news", and while changing the templates, I've noticed that while I can use things like {newsItem.datetime} or {newsItem.uid}, I cant use this with the custom fields i have created when extending the table tx_news_domain_model_news, like {newsItem.mycustomfield}
Edit: I have been pointed to this url and I've followed the instructions, but it's not working. This is my code
News.php
<?php
class Tx_WedoExtendnews_Domain_Model_News extends Tx_News_Domain_Model_News {
/**
* #var string
*/
protected $txWedoextendnewsLocation;
public function getTxWedoextendnewsLocation() {
return "this";
return $this->txWedoextendnewsLocation;
}
public function getWedoextendnewsLocation() {
return "that";
return $this->txWedoextendnewsLocation;
}
}
?>
Since I wasn't getting anything, I changed the returning values to string literals, to see if the problem was in the class and method names, or the property. Im still not getting anything. I think the underscored might be playing tricks on my code.
My extension key is wedo_extendnews and the new field is tx_wedoextendnews_location. Any ideas where the error lies?
Yes. To be able to access an object in fluid, you need the according setters in your model and maybe (not sure right now) an entry in the TCA.
If you want to access {newsItem.mycustomfield} you need an according setter in the model, like public function getMycustomfield() (note the get in get<Myfuncname>, it is mandatory).

Symfony 1.4: Check if form has errors inside form class

Is there a simple way in Symfony 1.4 to know whether a submitted form had any errors inside the form class? I'm familiar with the $form['some_field']->hasErrors() for templates but in this case I'd like to run a post-validator only if the form didn't have any errors with the standard validators. I'm basically after something like:
public function configure() {
// widgets
// standard validators
if (!this->hasErrors()) {
// run post-validator
}
}
The API documentation is as cryptic as usual. Thanks in advance.
Since the validation is perfom on the bind call, I don't see other place to post validate on error than in the bind function. So, in your form class:
public function bind(array $taintedValues = null, array $taintedFiles = null)
{
parent::bind($taintedValues, $taintedFiles);
if ($this->hasErrors())
{
// do post validate
// you can access values from your form using $taintedValues
}
}
But you will have to manually call the validator instead of just define a new one (since the bind process has already been done).