Can I pass parameters to a content slot from the calling ISML? - demandware

I'd like to be able to pass some supplementary information to a Content Slot, either through a request scope variable or some other means.
I've tried this in my calling ISML:
<isset name="message" scope="request" value="I want to be an Air Force Ranger" />
<isslot id="slot-message" context="global" description="banner"/>
And in the rendering template for the slot I have:
<iscontent type="text/html" charset="UTF-8" compact="true"/>
<iscache type="relative" hour="24"/>
<h3>${request.custom.message}</h3>
However, in the output HTML, I just get:
<h3>null</h3>
Is there some way I can pass an Object or String to a Content Slot?

Content asset don't have access to the data created or passed to ISML. However, a workaround can be done by adding the data to the DOM and then reading it inside the content asset:
<div class="banner-data" data-message="${message}">
<isslot id="slot-message" context="global" description="banner"/>
</div>
Then, in your content asset, you can read the message and use it:
<script>
var bannerData = $('.banner-data').data();
var message = bannerData["message"];
</script>

Content Assets is not aware of the page they are embedded in. This is by design. You can however embed HTML inside your content by using $include()$ which fetches html from a named controller or link to another page on the site using any of the $url-methods.
In the Content Templates it is further possible to reference data from the contentslot or from the content itself using: ${slotcontent} and ${slotcontent.content} respectively.

Related

How to use onclick method inside AEM component

Am having a AEM6 html component, am getting the values from dialog and using it inside the component via the .js file and using the return properties.
I could able to get the authored values but it is getting null or empty when am using it inside the onclick method. Please find below the code snippet below.
<div data-sly-unwrap data-sly-use.test="test.js"></div>
<a href="#" class="${test.testId}" id="${test.testId}" onClick="toggleDraw('${test.testId}')" >
The content I authored is getting displayed in class and Id, but it is not displaying in the onClick method.
Below is the Output am getting after authoring.
<a href="#" class="get-a-quote" id="get-a-quote" onClick="toggleDraw('')" >
Output I needed is :
<a href="#" class="get-a-quote" id="get-a-quote" onClick="toggleDraw('get-a-quote')" >
This should do the trick:
<a data-sly-test.variable123="toggleDraw('${test.testId}')" href="#" class="${test.testId}" id="${test.testId}" onclick="${variable123 # context='attribute'}" >
You need to put the function call in a variable because of the nested single quotes. And you need to manually set the context in this case. If "attribute" does some escaping you do not like, you could use "unsafe" - this will end in all escaping mechanisms being disabled. That might or might not be a security issue for your application.
HTH

Tapestry 5 custom component in form - access during validation

A have problem with accessing my custom components (which are used as parts of the form).
Here is the story:
I have dynamic form which have few modes of work. Each mode can be selected and loaded into form body with AJAX. It looks like that (template):
<t:form t:id = "form">
<p class= "calcModeTitle">
${message:modeLabel}: <select t:id="modeSelect"
t:type="select"
t:model="modesModel"
t:value="selectedMode"
t:blankOption="NEVER"
t:encoder="modeEncoder"
t:zone = "modeZone"
/>
</p>
<div class="horizontal_tab">
<t:errors/>
</div>
<t:zone t:id="modeZone" id="modeZone" t:update="show">
<t:if test="showCompany">
<t:delegate to="block:companyBlock" />
</t:if>
<t:if test="showPersonal">
<t:delegate to="block:personalBlock" />
</t:if>
<t:if test="showMulti">
<t:delegate to="block:multiBlock" />
</t:if>
</t:zone>
<t:block id="companyBlock">
<t:modes.CompanyMode t:id="company"/>
</t:block>
<t:block id="personalBlock">
<t:modes.PersonalMode t:id="personal" />
</t:block>
<t:block id="multiBlock">
<t:modes.MultiMode t:id="multi" />
</t:block>
<div class="horizontal_tab">
<input type="submit" value="${message:submit_label}" class="submitButton thickBtn"/>
</div>
</t:form>
AJAX works pretty well and form changes accordingly the "modeSelect" state. But i run into problem when submitting the form. I have in class definition hooks for components placed as:
//----form elements
#Component(id = "form")
private Form form;
#InjectComponent
private CompanyMode company;
#InjectComponent
private PersonalMode personal;
#InjectComponent
private MultiMode multi;
where *Mode classes are my own components, containing form elements and input components. I planned to get access to them during validation, and check values supplied by user with form, but when I am trying to reach anything from them I've got nullPointerException - it seems that component are not initialized in my class definition of form. On the other hand form component is injected properly (I am able to write some error for example). I am a bit lost now. How to properly inject my components to class page containing the form?
Dynamic forms in tapestry are a bit complicated. Tapestry passes a t:formdata request parameter which contains the serialized form entities. This is then used serverside in the POST to re-hydrate initial form state. This must be kept up-to-date with what the client sees.
If you want to add dynamic content to a form via ajax, you will need to use the FormInjector. You might want to take a look at the source code for the AjaxFormLoop to see an example.
If you want to render hidden form fragments and make them visible based on clientside logic, you can use the FormFragment
From tapestry guide:
A block does not normally render; any component or contents you put
inside a block will not ordinarily be rendered. However, by injecting
the block you have precise control over when and if the content
renders.
Try to use here either "t:if" or "t:delegate".
Something like this:
<t:zone t:id="modeZone" id="modeZone" t:update="show">
<t:delegate to="myBlock" />
</t:zone>
<t:block t:id="companyBlock">
<t:modes.CompanyMode t:id="company"/>
</t:block>
<t:block t:id="personalBlock">
<t:modes.PersonalMode t:id="personal" />
</t:block>
<t:block t:id="multiBlock">
<t:modes.MultiMode t:id="multi" />
</t:block>
java:
#Inject
private Block companyBlock, personalBlock, multiBlock;
public Block getMyBlock(){
if (getShowCompany()) return companyBlock;
if (getShowPersonal()) return personalBlock;
return multiBlock;
}

Passing AngularJS variable through form input field does not work

I have an iFrame that has content on a different domain, that I also control. I like to pass confidential data from the parent to the iFrame. Therefore, I do not want to pass it via query string or URL. I like to pass it via Form hidden input fields. It works if the values of the fields are text. However, it does not work if I use AngularJS variables as values for the fields.
Below is my code.
{{session.user.user_ID}} and {{i18n.domain}} works in this HTML file and writes the correct values to the webpage.
<form id="form_frame" action="http://other.mydomain.com/forIframe.php" method="post" target="output_frame">
<input type="hidden" value="{{session.user.user_ID}}" name="id" />
<input type="hidden" value="{{i18n.domain}}" name="domain" />
</form>
<iframe name="output_frame" width="400" height="400">
</iframe>
<script language="JavaScript" type="text/javascript">
document.getElementById("form_frame").submit(); // automatically submit the form
</script>
I have this in my forIframe.php file, which is the file that writes the content for the iFrame:
echo 'user ID is: '.$_POST['id'];
However, the above writes this:
user ID is: {{session.user.user_ID}}
Why doesn't this AngularJS variable parse correctly into the value attribute of the input field? How do I pass the values in {{session.user.user_ID}} and {{i18n.domain}} securely to my PHP file in my iFrame?
Elements inside the iFrame do not inherit the scope of the parent. You best bet is to use messaging i.e. $broadcast and $on : http://plnkr.co/edit/Osa5MNKiJKzsi7wAUXgM?p=preview

upload file and text in same view grails

I am having trouble getting a text input and a file upload from the user both of which I save to the database. I have two forms in the .gsp page one is for the text inputs and another is for the file upload. I am able to either save the file or get the text input, but I can not do both. When I place my submit button inside the tags for the textfield inputs it saves those, and when I place it in the tag it saves the file, but how can i get it do both on the click of a single submit button. I don't want to have multiple submit buttons. The two forms call upon the same method to save the data.
The example on this site is what I am looking for but it doesn't say how the information gets sent with the click of a single submit button:
http://www.ibm.com/developerworks/java/library/j-grails06099/index.html
All the <g:uploadForm...> tag does is set the form enctype to multipart/form-data. To upload standard text inputs and files I usually just do the following:
//GSP
<g:form method="post" enctype="multipart/form-data" action="update">
<input type="text" name="myTextField" id="myTextField" />
<input type="file" id="myFile" name="myFile" />
<g:actionSubmit class="save" action="update" value="${message(code: 'default.button.update.label', default: 'Update')}" />
</g:form> //closing tag fixed
Then what you do in your controller depends on how you are saving the uploaded file. If you are saving it into a byte [] myFile it will automatically bind if the field name is set correctly, so you don't have to do anything - it just works.
//controller
myInstance.properties = params //binds text as well as upload files
If you are saving it to the file system you could do something like this (straight from the manual):
//Controller
def f = request.getFile('myFile')
if (f.empty) {
flash.message = 'file cannot be empty'
render(view: 'uploadForm')
return
}
f.transferTo(new File('/some/local/dir/myfile.txt'))
response.sendError(200, 'Done')
The submit button submits the contents of the form it's contained within. The answer to your question is either: a) have 1 form and 1 submit button, or b) have 2 of each.
it also works if instead of having the <g:form> you just make it an <g:uploadForm> tag

Disabling data detectors for a specific HTML element in a UIWebView

Does anyone know if it's possible to disable the data detectors for phone numbers, email addresses etc in a UIWebView, for specific HTML elements only?
I'd like the detectors to be active for most of the content loaded into the UIWebView, but disable it in certain areas.
If this is possible, I'm assuming it would be achieved by using an HTML attribute in the loaded content (rather than setting some sort of UIWebView property), e.g.
<html>
<body>
<h1 datadetectors="off">Header text with number 9123 3456</h1>
<p>Body text with number 9872 4567</p>
</body>
</html>
In this example, the number in the <p> would be detected as a phone number due to setting webview.dataDetectorTypes = UIDataDetectorTypeAll, whereas the number in the <h1> would not.
you should use <meta name = "format-detection" content = "telephone=no">
Hope it helps
you can put the attribute
x-apple-data-detectors="false"
but unfortunately this seems to work only for tags.
I ended up using this solution:
666-777-777
besides disabling the telephone numbers "detection", this also prevents adresses and other detection to run.
If you control the web content you can use jscript (via jquery) to write your own data detectors. If you don't control the content you could insert and execute the jscript using stringByEvaluatingJavaScriptFromString: once webViewDidFinishLoad: is called.
In WKWebView Disable all Data Detector Types in Attributes inspector. This will solve your problem
Since an "a" tag will be inserted for you with the x-apple-data-detectors in it, you could write the tag yourself with x-apple-data-detectors set to false.
Original code:
<div class="my_time">17:02</div>
will be transformed to:
<div class="my_time">
<a href="x-apple-data-detectors://1" dir="ltr"
x-apple-data-detectors="true"
x-apple-data-detectors-type="calendar-event"
x-apple-data-detectors-result="1"
style="color: rgb(169, 169, 169);
text-decoration-color: rgba(169, 169, 169, 0.258824);">14:18
</a>
</div>
You can prevent this by writing your code as following...
<div class="my_time">
<a x-apple-data-detectors="false" style="text-decoration: none">17:02</a>
</div>