drupal 8 show field twice - drupal-theming

I created a custom bundle (content type) and I've created fields
One of those field is a file type field, is a video file, stored in the private storage. I installed the videojs module to allow to watch the video.
I need to show this field twice in the node page. One in the generic file formatter that allows the user to download the file, and I also need to play the video. I decided to set up as generic file formatter and customize the twig template to show again with the video player.
I achieve to show twice with the settings formatter (generic file) with this code in the node--mybundle--full.html.twig template
{{ content.field_sd_video }}
I thought it would be something easy like field+formatter:
{{ content.field_sd_video|videojs_formatter }}
But I can't find what is the simple way to achieve this. May be it's necesary more a tricky way ?

I finally found the solution, I put this code in preprocess node function. It has to be easy, but not easy to know how ;)
function mytheme_preprocess_node(&$variables) {
$variables['video_caption'] = $variables['node']->get('field_video')
->view(array(
'label' => 'hidden',
'type' => 'videojs_player_list'
));
}
and I only has to add this line in twig file:
{{ video_caption }}
in my case node--mybundle--full.html.twig template
For those arrive here looking for something similar
I was inspired by Twig Recipes on page 41
It was usefull for me Twig debugging. Playing with kint and node variable and the classes used to wrap the information. Then I found that the field comes with [FileFieldItemList] and then I found the view method that uses [EntityViewBuilderInterface]

Related

Where can I inspect Vue.js generated render functions?

An exception breakpoint once led me to a render function generated by the Vue template compiler for one of my Vue components.
This striked me as a "Hey, I now understand how this template system works!", but I didn't pay attention to where that was in the webpack tree.
Now I'd like to inspect the code for other components and may be set a breakpoint here and there, but when I browse the active javascript sources in the browser debugger pane, I can't find any of this generated code.
It looks like the compiled render functions can be found in the sources tree under the . folder of webpack://. It can be a bit tricky to find the right one though because there are multiple files for each .vue file. The other files will contain other bits of the component. The file containing the render function should be pretty obvious when you find it, it should start var render = function() {. For example, in one of my test applications I can see the render function for app.vue at webpack:///./src/app.vue?91e4, though that last part will vary.
If you want to insert a breakpoint for your own component then you can sneak it in via a method. This can also be a quick way to find the right file.
Within the template, make a call to a method, I've called it breakpoint:
{{ breakpoint() }}
Then in the method:
breakpoint () {
debugger
return ''
}
You can then walk one level up the stack to see the compiled render function.
Of course you don't necessarily have to use a debugger statement for this. You could just set a browser breakpoint in a suitable method (or introduce one if one doesn't already exist). So long as the method is called within the template it should give you access to the compiled render function.
To set a breakpoint that way you should just need to navigate to the relevant .vue file in the webpack:// section of the sources tree. That file is usually easy to find directly under the webpack:// heading.
Update:
Once you've found the file containing the render function using a breakpoint you can then find the file in the sources tree using 'Reveal in sidebar':

Server Side Rendering Vue with ASP.NET Core 2

I'm trying to understand the usage and limitations of server side rendering with vuejs when using aspnet core.
I used this starter kit for aspnet core and vuejs to setup a simple vue site, which is running based on the code here: https://github.com/selaromdotnet/aspnet-vue-ssr-test/tree/master
I then modified the project to update the aspnet-prerendering and added vue-server-renderer, compiling a hodgepodge of sources to cobble together this update: https://github.com/selaromdotnet/aspnet-vue-ssr-test/tree/ssr
If I run this project, the site appears to load fine, and if I turn off the javascript in the browser, I can see that it does appear that the server-side rendering executed and populated the html result:
however, because JavaScript is disabled, the content isn't moved into the dom as it looks like it is trying to...
My understanding of server-side rendering is that it would populate the html entirely and serve a completed page to the user, so that even if JS was disabled, they'd at least be able to see the page (specifically for SEO purposes). Am I incorrect?
Now I believe modern search engines will execute simple scripts like this to get the content, but I still don't want a blank page rendered if js is disabled...
Is this a limitation of server-side rendering, or perhaps specifically ssr with vue and/or aspnet core?
or am I just missing a step somewhere?
Edit: more information
I looked at the source code for what I believe is the method that prerenders the section here: https://github.com/aspnet/JavaScriptServices/blob/dev/src/Microsoft.AspNetCore.SpaServices/Prerendering/PrerenderTagHelper.cs
The line
output.Content.SetHtmlContent(result.Html);
has a null value for result.Html. However, when I manually edit this value to put a test value, it also doesn't render to the output html, and the app div tag is still empty...
If I'm doing something wrong to populate the result.Html value with the expected output, that's one thing, and I would appreciate some help in doing that, especially since the output html appears to be found, since it's in the script that immediately follows...
However, even if I were to populate it, it appears it's being skipped, as evidenced by me manually changing the value. is this a bug in the code or am I doing somethigng wrong, or perhaps both?
As you correctly noticed, for your project, result.Html inside the tag helper is null. So that line cannot be the location where the output is being generated. Since the HTML output from your prerendering script also does not include a script tag, it is clear that something has to generate that. The only other line that could possible do this is the following from the PrerenderTagHelper:
output.PostElement.SetHtmlContent($"<script>{globalsScript}</script>");
That would fit the observed output, so we should figure out where the globalsScript comes from.
If you look at the PrerenderTagHelper implementation, you can see that it will call Prerenderer.RenderToString which returns a RenderToStringResult. This result object is deserialized from JSON after calling your Node script.
So there are two properties of interest here: Html, and Globals. The former is responsible for containing the HTML output that finally gets rendered inside the tag helper. The latter is a JSON object containing additional global variables that should be set for the client side. These are what will be rendered inside that script tag.
If you look at the rendered HTML from your project, you can see that there are two globals: window.html and window.__INITIAL_STATE__. So these two are set somewhere in your code, although html shouldn’t be a global.
The culprit is the renderOnServer.js file:
vue_renderer.renderToString(context, (err, _html) => {
if (err) { reject(err.message) }
resolve({
globals: {
html: _html,
__INITIAL_STATE__: context.state
}
})
})
As you can see, this will resolve the result containing just a globals object with both html and __INITIAL_STATE__ properties. That’s what gets rendered inside of the script tag.
But what you want to do instead is have html not as part of globals but on the layer above, so that it gets deserialized into the RenderToStringResult.Html property:
resolve({
html: _html,
globals: {
__INITIAL_STATE__: context.state
}
})
If you do it like that, your project will properly perform server-side rendering, without requiring JavaScript for the initial view.

how to create a pdf editor for grails

In my Grails project I'm using the PDF plugin to generate PDFs from gsp page.
It works well, but I would like to add more functionalities to users, so I would like to allow user to edit the PDF basic template (defined in a gsp page), in particular I would like to allow the editing of the text inside the template and store it somewhere.
Anybody knows how could it be done?
If you only want to change the text, you could store the edited text in a database with the user id and loading it into the gsp page instead of the standard text.
If you also want to change the style of the page you could try to store the whole gsp page in the database and let the user editing it with an HTML Editor.
that's how i would start with, maybe someone has an better idea
The underlying components of the pdf plugin don't strictly require a .gsp file. It simply uses .gsps rendered as strings and feeds those into the flyingsaucer lib. So you could use a WYSIWYG type editor to allow users to create html snippets, save those strings somehow and then feed those though to the flyingsaucer libs yourself. just look into the included service methods of the plugin for an example. That might sound scary, but it really isn't very complicated.
You might want to wrap the user generated content with some of your own HTML markup for sanity and styling purposes of course, but the idea you are going for is entirely doable.
You could have a GSP that behaves of two different ways. First of all the GSP will be rendered in a Editable state. In this state the user could do some edits in some parts of the GSP. After that, the GSP will be rendered in a Preview state, where user could check the modifications that he has done in the previous step (nothing can be edited in this state). Finally, the GSP will be rendered as a PDF (using Grails Rendering Plugin).
Note that user will not edit the GSP itself. You need to allow him to edit through HTML elements as Text Areas, for instance. In this case we're using an WYSWYG editor. This editor allows the user to put text as Bold, Italic, etc.
Therefore, the most important step of this solution is to distinguish the two states in the same GSP. To do that you can use a boolean variable (called editing, for instance). This variable, if true, will render the GSP with the elements that will allow him to perform changes in the document. For other side, if the editing variable is false, the GSP will be rendered just with texts, not allowing any kind of editing.
The user could Check or Uncheck checkboxes (to show or hide some part of the document) and write or change texts in the Text Areas elements.
Below I'll show how this solution works.
GSP
The GSP is a template GSP and is called _quote.gsp
The piece of code below shows the use of the editing variable. Note that if editing = true, then a textarea is rendered and user can edit the text. There is a standard text that can be changed.
The post variable keeps what user has done after the editing phase. We use JQuery serialize to get all paramaters and pass it to a Grails Controller.
<p>
<g:if test="${editing}">
<pgs:textArea html="true" autosize="true" name="fraseInicial" rows="2" cols="80">
${post?.fraseInicial?post.fraseInicial:"Conforme sua solicitação, a empresa tem a satisfação de informar-lhe os métodos e preços."}
</pgs:textArea>
</g:if>
<g:else>
${post.fraseInicial}
</g:else>
</p>
pgs:textArea is a specific taglib of this system and is used to render a WYSWYG editor, you can replace it for a simple TextArea HTML element.
An example with checkbox:
<g:if test="${editing || post.temPrazoAnalise}">
<h1>
Teste teste
</h1>
<g:if test="${editing}"><g:checkBox name="temPrazoAnalise" value="${!post?true:post?.temPrazoAnalise == null?false:true}"/></g:if>
<g:if test="${editing || post.temPrazoAnalise}">
<p>Teste teste teste </p>
</g:if>
</g:if>
Controller
The previewQuote() is called from an AJAX call that serializes (via JQuery) all parameters of GSP.
The back() action allows the user to back to the editing state from the preview state. This is the reason why we set session["paramsReport"] = params inside previewQuote(). Doing this way it's possible to use session["paramsReport"] inside back() and restore the values changed by the user.
def editQuote() {
def quote = Quote.get(params.id)
render(template: "/quote/report/quote", model: [editing:true, quote:quote])
}
def previewQuote() {
Quote quote = Quote.get(params.id)
session["paramsReport"] = params
render(template: "/quote/report/quote", model: [quote:quote, post:params])
}
def back() {
def quote = Quote.get(params.id)
if (session["paramsReport"]) {
render(template: "/quote/report/quote", model: [editing:true, post:session["paramsReport"], quote:quote])
}
}
def generateQuote() {
Quote quote = Quote.get(params.id)
def f = new File(grailsApplication.mainContext.servletContext.getRealPath("/app/temp/${quote.code}.pdf"))
if (f.exists())
f.delete()
f.withOutputStream { os ->
pdfRenderingService.render([template: '/quote/report/quote', model: [quote:this, post:session["paramsReport"], pdf:true]], os)
}
}
This solution was developed by wanderson-santos (https://stackoverflow.com/users/128857/wanderson-santos) and me.
I hope you understand the overall idea of the solution. I understand that could be a bit complicated at a first view. Anyway, is a solution that allows flexibility for this kind of requirement (i.e. allow the user to customize a report before the PDF is generated).

how to integrate hebo html template into yii framework

how to integrate hebo html template into yii framework
I am new to using yii framework.I download hebo template from
http://www.webapplicationthemes.com/hebo-responsive-html5-theme/
I can installed template hebo but i don´t work with ie.
Don´t work fluid bootstrap.
go to views/layouts/main.php and delete html comment " <- Require the header ->" instead you can add it as php comment. This comment appears before tag and it causes IE doesn´t understand HTML5.
Did you convert the theme to work with Yii?
One of the problems with this kind of theme is that it has multiple page types and this is harder to replicate in Yii. By default, Yii has no concept of page type unless you code this into the controller using layouts ....
At the very simplest level, the conversion could be based on the fullwidth page,, converting the mainContent divs to inject $content. You would then need to change a layout to use single column ...
I've just completed this for another of their templates and it doesn't take too long - though if any one has a better idea for page types I would be very interested ....

DHTML - Change text on page using input field

I need to create a code to change an example text to a user-defined value when the user types in an input field (Similar to the preview field when writing a question on Stack Overflow).
This needs to be achieved without the use of HTML5 or Flash as the users will be running IE8, not all will have Flash plug-ins installed.
As such I have started by looking at DHTML to achieve the desired effect. Currently I can change the example text when a user types in the input field but only to a pre-defined value ("Example" in the code below), how should I edit this code to display the user-defined value?
JS
function changetext(id)
{
id.innerHTML="Example";
}
HTML
<form>
Content:<input type="text" id="input" onkeyup="changetext(preview)" />
</form>
<p id="preview">No content found</p>
You need to have something like this in the function:
function changetext(id){
var info = document.getElementById('input').value();
id.innerHTML = info;
}
This js is not fully correct. I would highly recommend you start using a javascript library like jQuery. It makes this a menial task.
Edited:
jQuery will work in IE8 just fine. in jQuery you will not need to attach js to your input. The code would look like this.
$('#input').click(function(){
$('#preview).html(this.val());
});
It is a lot cleaner and doesnt have js in the html.