How to retrieve layout of an item using JSS - sitecore

I am really new to JSS and I am very confused by the docs and how Sitecore is supposed to assemble layout information. I am trying to retrieve layout information of an item using JSS for one of our MVC project. The item in question renders fine in the browser using our traditionnal MVC stack. However I am unable to retrieve layout information of that item using JSS.
The item in question is based on the standard template and has the following presentation/layout details:
The layout points to a cshtml file.
The cshtml file contains the HTML layout, and a placeholder rendered using #Html.Sitecore().Placeholder("Menu")
The content of the placeholder is defined in Sitecore Layout Details dialog using a control/rendering named "Menu".
The rendering "Menu" points to a controller named Web.Controllers.MenuController and action named GetMenu
Content of the cshtml file:
#using Sitecore.Mvc
<main id="main" class="content group advise-area" role="main">
<div class="inner inner-carousel advise-area-content">
<div class="row">
<div class="col-2-2">
#Html.Sitecore().Placeholder("Menu")
</div>
<div class="col-2-2">
#Html.Raw(Model.Content)
</div>
</div>
</div>
</main>
When retrieving the layout information of the item using the render endpoint (/sitecore/api/layout/render/jss?item={item_id}&...). I get the fields values of the item, but I do not get any presentation details nor placeholder information.
{
"sitecore": {
"context": {
"pageEditing": false,
"site": {
"name": null
},
"pageState": "normal",
"language": "fr",
"itemPath": "/my-item"
},
"route": {
"name": "prendre-route-securite",
"displayName": "prendre-la-route-en-toute-securite",
"fields": {"Content": {"value": "My Content"}},
"databaseName": "web",
"deviceId": "fe5d7fdf-89c0-4d99-9aa3-b5fbd009c9f3",
"itemId": "85cac673-2cfb-496c-ba62-0f1d634ae241",
"itemLanguage": "fr",
"itemVersion": 1,
"layoutId": "b39337a1-8bb5-44c3-ba97-0dce8ef517f6",
"templateId": "34c34e2b-f2ac-405f-afb3-d0185bc936bb",
"templateName": "ArticleZoneConseils",
"placeholders": {}
}
}
}
The documentation says I am supposed to put some values inside the Layout Service Placeholders field of the layout. But I have no clue of what I should put in there to get the placeholder data showing in the REST query.

Related

ember-bootstrap - rendering "radio" inputs

Using the Ember addon ember-bootstrap I can make a set of radio buttons like this :
{{form.element controlType="radio" label="Fruit Type" property="radio" options=radioOptions optionLabelPath="label"}}
with a Controller that looks like this :
export default Controller.extend({
init() {
this._super(...arguments);
this.radioOptions = [
{
label: 'Citrus',
value: 'C',
inline: true
},
{
label: 'Non-Citrus',
value: 'N',
inline: true
}
];
}
});
The relevant doco is here https://www.ember-bootstrap.com/#/components/forms .
However what I can't do is provide a custom value to each radio button so that I end up with rendered HTML like this :
<label>Citrus</label>
<input type="radio" value="C">
<label>Non-Citrus</label>
<input type="radio" value="N">
I have looked at "Custom Controls" on https://www.ember-bootstrap.com/#/components/forms but I can't see how that applies to this case.
EDIT: Just to be clearer about why I want to do this I want to display the readable label (eg "Citrus") but have the non-readable value ("C") available to send back to the server (because the server thinks in terms of "C" or "N".
It's not essential I could send "Citrus" back and map it around on the server but I just thought this would be very straightforward.
Looking at the part of the doco starting with "You can also just customize the existing control component:" on https://www.ember-bootstrap.com/#/components/forms it does seem like you should be able to do the sort of thing I'm after but the example shown doesn't address the use of a value attribute and I can't figure out how to .
You don't need to have the HTML rendered like that. if you want to access the checked radio, simply it is the property name dot value like radio.value.
Here how to get it in the on submit action:
actions: {
onSubmit() {
alert(this.radio.value)
}
}
I had exactly the same issue but I finally solved it. You have to use form.element in block mode. Why is it also necessary to also write an action to update the value? I have no idea!
In my implementation, I'm using Ember changesets and my property is called usageType. I hope it's clear enough to adapt for your needs.
I'm also using Ember Truth Helpers, which is what the {{eq opt.value el.value}} part is. It sets checked to true if the input value is equal to the current-selected value.
# my-component.js
actions: {
selectUsageType(option) {
return this.set('changeset.usageType', option);
}
}
# usage-type-options.js (imported in component JS)
[{
label: 'First label',
value: 'A'
},
{
label: 'Second label',
value: 'B'
}]
# Etc.
# my-component.hbs
# I'm not using angle-bracket invovation here, oops
{{#form.element
property="usageType"
label="My label" as |el|
}}
{{#each usageTypeOptions as |opt|}}
<div class="form-check">
<input
type="radio"
class="form-check-input"
id="{{el.id}}-{{opt.value}}"
checked={{eq opt.value el.value}}
onchange={{action "selectUsageType" opt.value}}
>
<label for="{{el.id}}-{{opt.value}}" class="form-check-label">
{{opt.label}}
</label>
</div>
{{/each}}
{{/form.element}}

Dynamically setting select key in Ember within select field

So I have an API that generates forms from a database. The API for the fields returns:
{
"formFields": [
{
"module": 1,
"fieldName": "Global Title",
"fieldPosition": "1",
"fieldType": "select",
"fieldEditable": true,
"dataTable": "message",
"dataKey": "calling_gt",
"dataValue": "id",
"id": 1,
"createdAt": "2015-10-15T13:59:30.764Z",
"updatedAt": "2015-10-15T13:59:30.764Z"
}
]
}
I have multiple Ember components. Essentially an Add Parameter component that loops through the fields related to the component. Below is loading the select component passing in the Model from the database table and the fields to use for the Key->Value:
{{#each model.fields as |field|}}
{{#if (eq field.fieldType "select")}}
{{form/select-field model=field.dataTable label=field.fieldName key=field.dataKey value=field.dataValue selected=1}}
{{/if}}
{{/each}}
The select-field component then generates a select that brings out the Model data from the values provided in the Add Parameter component, like so:
<div class="form-group">
<label for="{{key}}">{{label}}</label>
{{#x-select value=optionValue action="selectOption" class="form-control" id=key}}
{{#each componentModel as |option|}}
{{#x-option value=option.calling_gt}}{{option.calling_gt}}{{/x-option}}
{{/each}}
{{/x-select}}
</div>
But as you can see, in x-option, I'm currently hard-coding the values, where they should be using the key=field.dataKey. But as I'm looping through and my componentModel -> Options don't hold that variable, I'm not sure how to pass it into the x-option value.
My component.js for select-field looks like this, if it helps:
import Ember from 'ember';
export default Ember.Component.extend({
componentModel: function() {
return this.store.findAll(this.get('model'));
}.property(),
actions: {
selectOption(value, component) {
Ember.Logger.debug("Option " + component + " with value " + value + " selected");
this.set('optionValue', value);
}
},
});
Does anyone know how to bring out the data using the key and value passed into the select-field component?
Sounds like you might be able to use the get helper. http://emberjs.com/api/classes/Ember.Templates.helpers.html#method_get
{{#x-option value=(get option key)}}
{{get option key}}
{{/x-option}}

Dust.js context issue?

I have the following partial:
<ul class="navbar">
{#nav_links}
<li class="navbar__link {?sub_menu}more{/sub_menu}">
{label}
{?sub_menu}
<ul class="navbar__link--sub">
{#sub_menu}
<li class="navbar__link--sub {?sub_menu}more{/sub_menu}">
{label}
</li>
{/sub_menu}
</ul>
{/sub_menu}
</li>
{/nav_links}
</ul>
With JSON:
{
title: "page title",
nav_links: [
{
link: "home",
label:"Home"
},
{
link: "products",
label:"Products",
sub_menu: [
{link: "link1", label: "Product A"},
{link: "link2", label: "Product B"},
{link: "link3", label: "Products C", sub_menu: [
{link: "link3-1", label: "Sub Product A"},
{link: "link3-2", label: "Sub Product B"}
]},
]
}
]
}
The issue I've run into is the nested sub_menu property, all sub menu items add the more class regardless if they have a nested sub_menu or not. I thought the context would have shifted like it does with link and label, however it seems to still refer to the initial sub_menu like the first conditional and section tags do. I've renamed the nested sub_menu property in the JSON and partial tag, context works correctly then. Is there a way to still use the sub_menu property name? Or reference the child property such as sub_menu.sub_menu?
By default, Dust will walk up the context if it doesn't find a key at a certain level. However, you're wanting to explicitly check only the current level of the context. To do this in Dust, prefix the key with a dot:
<li class="navbar__link--sub {?.sub_menu}more{/sub_menu}">

Attaching metadata to array in model

I have the following model (see my previous question):
slide: {
"id": 1,
"name": "stack-overflow-page",
"type": "webpage",
"parameters": [
{"key": "url", "value": "http://stackoverflow.com"},
{"key": "extension", "value": "/questions/ask"}
]
}
Each parameter has metadata, depending on the slide type:
widget: {
"id": "webpage",
"description": "Renders a webpage.",
"parameters": [
{"key": "url", "type": "string", "description": "The base URL to show."},
{"key": "extension", "type": "string", "description": "The rest of the URL to attach, or any parameters."}
]
}
Currently, the "widget" metadata is loaded in the controller (note: ember-cli is used here):
import Ember from 'ember';
export default Ember.ObjectController.extend({
widget: function() {
return this.store.find('widget', this.get('model.type'));
}.property('model.type'),
});
However, when using the parameters in the template, I see no way to look up the metadata information for each parameter (for example, to show the parameter's description).
{{#each parameters}}
<div class="form-group">
<label class="col-sm-2">{{key}}</label>
<div class="col-sm-10">
{{input type="text" value=value class="form-control"}}
</div>
</div>
{{/each}}
Additionally, if I attached the metadata to each parameter in the model, I assume it would be sent back to the server unnecessarily, since parameters is simply a DS.attr(). Is there a good way to look up the metadata information for each parameter?
I believe the EmbeddedRecord Mixin is what you're looking for. It was just abstracted out of the Active Model serializer and added to the generic REST serializer in the most recent EmberData beta (Ember Data v1.0.0-beta.8), so you may need to upgrade to use it. You'll still need to create a DS.Model for 'parameters' with two fields 'key' and 'value' for this to serialize correctly.
You can use the extractMeta hook from the JSON or REST Serializer -> https://github.com/emberjs/data/blob/master/packages/ember-data/lib/serializers/json_serializer.js#L945 to parse your meta information.
If you want to access the metaData on your manyArray, you will need this patch -> https://github.com/emberjs/data/commit/8544c29419d1ef909762a50beb434c219a34c846
I completely forgot about it, I can merge it in a day or two so you don't have to edit ED yourself.

Windows 8 JS & html5 app - foreach within template

How do I loop thru items in a WinJS.Binding.Template within my WinJS.UI.ListView control?
My data:
{ category: 'Sports',
items: [
{ title: 'soccer'}, { title: 'tennis'}
]
}
What I want to do in my template:
<div id="myTmpl" data-win-control="WinJS.Binding.Template" style="display:none">
<h1 data-win-bind="innerText: category"></h1>
<div data-win-REPEATER="each: items">
<span data-win-bind="innerText: title"></span>
</div>
</div>
Because you want to nest the details of the items, I would recommend that you look at my answer to another question, which is very similar:
WinJS ListView and Template Binding
This has all the essential details.
That stated, theres no reason you cant integrate JQuerys templates here - you just need to find a way for them to work with the WinJS template / control contract.
Have you checked
http://code.msdn.microsoft.com/windowsapps/ListView-basic-usage-sample-fcc451db
Normally the loop is automatically (it will do based on the datasource information)
<div id="listView"
class="win-selectionstylefilled"
data-win-control="WinJS.UI.ListView"
data-win-options="{
itemDataSource: myData.dataSource,
itemTemplate: myTmpl,
selectionMode: 'none',
tapBehavior: 'none',
swipeBehavior: 'none',
layout: { type: WinJS.UI.GridLayout }
}"
></div>