Macro to get real current page - kentico

Not sure how to label the title of this question. I have a snippet of re-usable content with a Subscribe Icon + Social Icons. This snippet is used in almost every page on the site through a repeater.
What I want to do is to attach the CurrentDocument.DocumentName to the Subscribe Icon in order to know which page people came from, something like this:
Subscribe However, looks like that doesn't work. This string shows in the address bar when click on the link: www.domain.com/subscribe?p={%%20CurrentDocument.DocumentNamePath%20|(user)|(hash)34ce5eaa55a6a6ad89...%} I figure because CurrentDocument is actually referring to the snippet itself, not the real current page displaying in the browser. Could you help?

Is your repeater transformation aspx? If so, use <%# %>, so <%# CurrentDocument.DocumentName %>

If this is an ASCX transformation it is like a web user control, so you can call C# methods, try this
<%# CMS.MacroEngine.MacroResolver.Resolve("{%CurrentDocument.DocumentName#%}")%>
Or you can do linke in this in ACSX transformation:
<script runat="server">
string test = "";
protected override void OnInit(EventArgs e)
{
test = CMS.MacroEngine.MacroResolver.Resolve("{%CurrentDocument.DocumentName#%}");
}
</script>
<h1><%# test%></h1>
Consult MacroResolver class for other methods
P.S. Sorry I didnt check my answer in Kenitco for the frist time. Just make sure you calling MacroResolver from the right name space.

Related

How can I redirect to custom pages when a user click New/Edit/Display in a SharePoint list

We are replacing the forms for our lists with forms built with SPFx. Building and deploying the form is no issue. The problem is redirecting the form controls to this form (when a user opens an item or clicks new, etc...). Is there a recommended method of accomplishing this? I have been successful using two methods but they both seem volatile and hacky.
The first being replacing the entire form code using SharePoint designer. For instance, the new form code would be
<%# Page language="C#" %>
<html lang="en">
<head>
<script type="text/javascript">
const list = window.location.href;
const site = list.substring(0,list.toLowerCase().indexOf('/lists/'));
window.location.replace(site + "/SitePages/MyListForm.aspx");
</script>
</head>
<body>
</body>
</html>
This works sometimes... Upon saving, the form code seems to regenerate the form code but the redirect still works. However, if I open and save the code again, everything breaks and the list action goes back to default (clicking new would now show the 'New Item' call out instead of directing to the form).
The other method is opening the new/edit/display form in the browser, with ?toolpaneview=2 which allows me to add a script web part to the page (although it doesnt like to save) and add the script redirect in.
<script type="text/javascript">
const list = window.location.href;
const site = list.substring(0,list.toLowerCase().indexOf('/lists/'));
window.location.replace(site + "/SitePages/MyListForm.aspx");
</script>
this seems to be less volatile than the first method, but it still seems hacky. If I delete the original form web part, the form breaks and the list actions again revert to default. Editing the script requires visiting the form with ?contents=1 to delete the script web part and then I have to re-add it again using the toolpaneview method. In order to even save the web part change I have to click "Edit Web Part", which in turn saves it. There is no simple "Save" action which again makes me feel like this method is not intended to be done.
Is there any recommended way to accomplish these redirects? I've found plenty or tutorials online about setting up the list form, but nothing about this essential step.

How to access the values of web part properties in the layout?

In the Kentico Documentation I only found the info as below...
Is there any way to access the properties value in the layout as show below? I tried to use macro but it didn't work.
I just want to display the properties value in my custom layout. Any methods other than access through the code? I'm using portal engine, I have no idea how to access the code behind...
The layout is ASCX, so you won't be able to use macros as per your example.
If you just need the value, you can use the GetValue method. There's also GetStringValue, if the type of your property is a string
<% GetStringValue("MyPropertiesValue1", string.Empty); %>
If you need to render the value, you will need to call Page.DataBind() and use a data binding expression. Your layout would look something like this:
<%# GetStringValue("MyPropertiesValue1", string.Empty) %>
<%# GetStringValue("MyPropertiesValue2", string.Empty) %>
<script runat="server">
protected void Page_Load(object sender, EventArgs e)
{
Page.DataBind();
}
</script>
None if this is really elegant, so you might want to reconsider your approach.

Migrate custom admin pages with dialogs from 4.5.12 to 5.3.4

We have code to open dialogs for links on admin pages by calling the javascript function mgnlOpenDialog(), like this,
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
[#assign cms=JspTaglibs["cms-taglib"]]
<html>
<head>
<title>UCP Books</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<link href="${this.request.contextPath}/.resources/admin-css/admin-all.css" type="text/css" rel="stylesheet" />
<script type="text/javascript" src="${this.request.contextPath}/.magnolia/pages/javascript.js"><!-- --></script>
<script type="text/javascript">
function displayDialog()
{
if ( ! window.focus ) return true;
var path = "${this.path}";
var nodeCollection = null;
var node = "${this.nodeName}";
var paragraph = null;
var repository = "${this.repository}";
var dialogPage = ".magnolia/dialogs/author.html";
mgnlOpenDialog( path, nodeCollection, node, paragraph, repository, dialogPage );
return false;
}
</script>
</head>
<body id="mgnl" class="mgnlBgLight mgnlImportExport">
<h2>
${this.messages.get("module.books.pages.AuthorDetailPage.header")}
<span class="mgnlControlButton" onclick="displayDialog();">
${this.messages.get("module.books.pages.edit")}
</span>
</h2>
<div class="pageFrame">${this.content}</div>
</body>
</html>
Now we are migrating our site from 4.5.12 to 5.3.4, and I noticed that the dialog definitions got updated. Now when I click on the link, there is still the dialog popup, but the popup is blank with the old style "Save" and "Cancel" buttons displaying at the bottom. It seems we need to convert our admin pages to content apps. But to do it that way will require a lot of changes in our code. So I'd like to know if there is an alternative way to replace mgnlOpenDialog() function to invoke the dialogs when I click on the links on the admin pages.
Thanks very much!
Aiping
Yeah this doesn't work any longer. Assuming you needed to open the dialogs explicitly because you had content you were editing in other workspaces then website. Correct?
When migrating custom data to M5, if you had that content in data workspace, you can use migration task to move it from the shared workspace into separate workspace and to also migrate your dialog. Not sure at the moment if it generates also app for you, but if not you can use this script to create one.
Once you have dialog migrated (or created from scratch) and your app created (either via script above or manually) you can just simply open any content in that app for editing and copy url from there. That would be the url you need to call to open dialog for editing from anywhere. It will be something like http://<your host>:<your port>/<contextPath>/.magnolia/admincentral#app:<yourAppName>:detail;/path/to/edited/content:edit
of course, assuming your subapp is called "detail" and your edit action "edit" as suggested in the tutorial or generated by the script.
Good luck,
Jan
Thanks Jan!
This seems a right direction to go by calling the url,
http://<your host>:<your port>/<contextPath>/.magnolia/admincentral#app:<yourAppName>:detail;/path/to/edited/content:edit.
I've configured the detail subapp and added this line to my code,
title
and it works. I'll post more in details later.
Thanks,
Aiping
Jan, I tried your solution as I commented here and it works well, except for one issue. Here I'm pointing to several screenshots to better explain it.
https://plus.google.com/u/0/photos/103180294078685589341/albums/6081701864232931905
On the app_faqSearch_1.png, there is a search form only.
The app_faqSearch_2.png is the page with the search results.
When I click on the "faq0004" link on app_faqSearch_2.png, the app_faqSearch_3.png appears. The code behind the scenes is,
faq0004
The problem is when I close the dialog tab "/FAQ/TOPICS/COMMAS/...", on the app_faqSearch_4.png, the search results are not there anymore since the view got reloaded.
Is there a way to configure to prevent the view from being reloaded if it's already opened, like for this URL in my case, /magnoliaAuthor/.magnolia/admincentral#app:faqSearch:main;
Or is there a way to explicitly open a dialog, instead of an editor, by passing the node path and workspace when click on the link like "faq0004"? Similar way to open the "editMessage" dialog in "contacts" app.
Thanks very much,
Aiping

Exception trying to load tab from ajax request using Ext.NET

I'm using asp.net mvc with ext.net and I'm trying to create a set of tabs that load information only when they are selected by the user.
I can manage to load a partial view into a tab/panel using the ContentFromAction functions:
But I can't figure out how to populate a tab/panel only when a tab is selected.
I've based my project on the Ext.NET MVC Examples Explorer version 2.5 code base and this code on the TabPanel > Basic > Ajax Load example found here
I've cut down the example as far as I can to reproduce the problem:
In my view I create the tab and configure the loader (exactly the same as the example project):
Index.cshtml
X.Panel()
.ID("Tab3")
.Title("Ajax Tab")
.BodyPadding(6)
.AutoScroll(true)
.Loader(X.ComponentLoader()
.Url(Url.Action("Ajax"))
.LoadMask(m => m.ShowMask = true)
.Params(new Parameter("containerId", "Tab3"))
.Mode(LoadMode.Html)
)
It correctly calls into my controller (exactly the same as the example project):
Axax_LoadController.cs
using System.Web.Mvc;
namespace Ext.Net.MVC.Examples.Areas.TabPanel_Basic.Controllers
{
public class Ajax_LoadController : Controller
{
public ActionResult Ajax(string containerId)
{
return View("Ajax");
}
}
}
Which in turn displays the appropriate view in the tab after it's been clicked on:
Ajax.cshtml (this works)
#using Ext.Net.MVC
<div>
<p>I am content loaded via Ajax when the tab is selected</p>
</div>
The problem begins if I try to add controls in my view, as follows:
Ajax.cshtml
#using Ext.Net.MVC
#{ var X = Html.X(); }
<div>
<p>I am content loaded via Ajax when the tab is selected</p>
#X.TextField().Text("I am a text field")
</div>
This fails with the exception:
ItemTag validation (_tkn_1): Reference token (init_script) was not found.
If I modify the file Ext call to return Html as follows:
Ajax.cshtml
#using Ext.Net.MVC
#{ var X = Html.X(); }
<div>
<p>I am content loaded via Ajax when the tab is selected</p>
#X.TextField().Text("I am a text field").ToHtmlString()
</div>
It correctly renders the following text in my selected tab:
I am content loaded via Ajax when the tab is selected
<#:item ref="init_script" index="0">Ext.create("Ext.form.field.Text",{renderTo:"App.id534c5fe0f159f3fb_Container",value:"I am a text field"});</#:item><div id="App.id534c5fe0f159f3fb_Container"></div>
I believe that the ext.net code is written by #geoffrey.mcgill on stack overflow so I'm hoping he can help rescue me.
You need to use a PartialViewResult. Please look at these examples.
Partial Content
Partial Items
Personally, I would recommend to follow the Partial Items example. You always can wrap any non-Ext.NET content in an Ext.NET Container. The benefit of this approach is the fact that you don't need to worry about destroying Ext.NET components if you reload the content. Though, anyway, I would recommend to set up explicit IDs for Ext.NET components in a partial view. At least, for top level components.

Can I read the search scope selected in SharePoint from code behind

I have a search box web part. In that web part I have created an instance of SearchBoxEx like
SearchBoxEx par=new SearchBoxEx
par.goImageUrl=""
par.DropDownMode= DropDownModes.DisplayScopeDD;
Button sear= new Button();
sear.Click += new EventHnadler(sear_Click);
I have added a button to that search Box web part.Now I have to read the scope selected in the SearchBoxEx in the sear_Click event.Can anyone please guide me in the right direction
Any help would be really appreciated.
You could read the Request.QueryString["s"] parameter, even when it is a post, the SearchBoxEx adds it.
Edit
Based on the comments and new info, are you using 'pure' javascript? This would be a jquery example:Search
WARNING: You should change the site masterpage INSIDE your site with SharePoint designer, not the one in the C:\Program Files\etc... folder. You could also navigate to the http://yourportal/_catalogs/masterpage library and download a copy of the default.master to change it then upload it back to the library, do all this carefully, you can break your sharepoint very easily.
Insert above the </HEAD> tag in your masterpage:
<script type="text/javascript" src="http://jqueryjs.googlecode.com/files/jquery-1.3.2.min.js"></script>
<script type="text/javascript">
function newSearchResultsPageWithScope()
{
var scope = $(".ms-sbscopes select").val();
location.href = "/CustomResultsPage.aspx?s=" + scope;
}
</script>
The jquery portion is pretty straightforward, it gets the <td> with the class="ms-sbscopes", and the <select> element under it, then it sets the 'scope' variable to the selected value of the scopes dropdown.
Also, customizing the masterpage in a sharepoint site is fine, do not worry with that.

Resources