Add querystring to "asp-page" link in CORE razor pages - razor-pages

In CORE razor pages
<a asp-page="View" asp-route-ID="#item.ID" >View</a>
this creates a link to a page using a route to pass the ID and generates the following HTML
View
I want to add the contents of the querystring to this link so the generated HTML looks like
View
#Request.QueryString gets the entire querystring e.g. "?s=smith" but I can't find the way to add it to the end.
Any ideas.

This works for me (from https://www.learnrazorpages.com/razor-pages/tag-helpers/anchor-tag-helper):
<a asp-area="Identity" asp-page="/Account/Register" asp-route-view="personal">Text</a>
This routes you to: Identity/Account/Register?view=personal.
In "asp-route-view", the view can be anythin you need:
<a asp-area="Identity" asp-page="/Account/Register" asp-route-disco="party">Text</a>
routes you to Identity/Account/Register?disco=party.

Example Url :
https://localhost:44313/dados_pessoais?userid=1
Use: asp-route-youproperty="value"
Get user data sample
<a class="nav-link text-dark" asp-area="" asp-page="/dados_pessoais" asp-route-userid="1">Dados Pessoais</a>
c#
public void OnGet(int userid)
{
var usuario = Usuarios.Where(u => u.Id == userid).FirstOrDefault();
}

The asp router tag helpers will ensure the target page matches the format specified but assuming it does you can do something like the following:
<a asp-page="View" asp-route-ID="#item.ID" asp-route-s="#Request.Query["s"].ToString()">View</a>
The Request Query property can be used to access individual querystring parameters by name.

Related

POST FORM in node and receive data response back to same webpage

I have a webpage that takes form details, POSTS the data and should then show the results. I'm using express for my routing.
This all works fine by resending the data with the HTML template after the POST but I think there must be a better way by hiding the "results" HTML section then just showing it once the data is known from the form. I've shown a cutdown version of my pages below.
On first load, the page says "your result is undefined", which I would expect but is ugly.
I could remove the "result" section and create a 2nd HTML page to resend from the POST route with it in which would work but I think there must be a better way.
I want to hide the result section on 1st page load then make it appear on the button submit with the result data. I can get the section hide/unhide but I can't get the data results back to display them. On button submit the form results just appear in the weburl www.mywebsite.com/?data almost like a GET request
I have tried using FormData and npm 'form-data' in a POST but can't get it working following these examples https://javascript.info/formdata and https://www.npmjs.com/package/form-data.
My structure in Node is
Router.js file
return res.send(htmlFormTemplate({}));
});
router.post('/css',
[],
async (req, res) => {
let {data} = req.body;
///
result= do some calculation on {data}
///
return res.send(htmlFormTemplate({result}));
});
The htmlFormTemplate is a js file
module.exports = ({result}) => {
return `
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<form class="box" method ="POST">
<inputname="data" />
<button>Submit</button>
</form>
<script>
///tried form processing here
</script>
<section id="Results">
<ul><li>Your result is ${result}</li></ul>
</section>
</body>
</html>
`;
};
I'm self-taught and new so hope this makes sense and thanks for any help/ideas
You can check if the result variable is null before it gets to the section div:
${ result === null ? '' :
`<section id="Results">
<ul><li>Your result is ${result}</li></ul>
</section>`}
Like this, it wont show the result div if result if null.
There is a very simple to solve this problem,
just use some templating engine for ex EJS, its very easy to use and will help you better,
and your result is undefined because your using a promise and it might have happened that the response might have not come and you loaded the page. Just use await
return await res.send(htmlFormTemplate({result}));

Orchard CMS - Extending Users with Fields - exposing values in Blog Post

I'd like to extend the users content definition to include a short bio and picture that can be viewed on every blog post of an existing blog. I'm unsure of what the best method to do this is.
I have tried extending the User content type with those fields, but I can't seem to see them in the Model using the shape tracing tool on the front end.
Is there a way to pass through fields on the User shape in a blog post? If so, what is the best way to do it?
I also have done this a lot, and always include some custom functionality to achieve this.
There is a way to do this OOTB, but it's not the best IMO. You always have the 'Owner' property on the CommonPart of any content item, so in your blogpost view you can do this:
#{
var owner = Model.ContentItem.CommonPart.Owner;
}
<!-- This automatically builds anything that is attached to the user, except for what's in the UserPart (email, username, ..) -->
<h4>#owner.UserName</h4>
#Display(BuildDisplay((IUser) owner))
<!-- Or, with specific properties: -->
<h1>#T("Author:")</h1>
<h4>#owner.UserName</h4>
<label>#T("Biography")</label>
<p>
#Html.Raw(owner.BodyPart.Text)
</p>
<!-- <owner content item>.<Part with the image field>.<Name of the image field>.FirstMediaUrl (assuming you use MediaLibraryPickerField) -->
<img src="#owner.User.Image.FirstMediaUrl" />
What I often do though is creating a custom driver for this, so you can make use of placement.info and follow the orchard's best practices:
CommonPartDriver:
public class CommonPartDriver : ContentPartDriver<CommonPart> {
protected override DriverResult Display(CommonPart part, string displayType, dynamic shapeHelper) {
return ContentShape("Parts_Common_Owner", () => {
if (part.Owner == null)
return null;
var ownerShape = _contentManager.BuildDisplay(part.Owner);
return shapeHelper.Parts_Common_Owner(Owner: part.Owner, OwnerShape: ownerShape);
});
}
}
Views/Parts.Common.Owner.cshtml:
<h1>#T("Author")</h1>
<h3>#Model.Owner.UserName</h3>
#Display(Model.OwnerShape)
Placement.info:
<Placement>
<!-- Place in aside second zone -->
<Place Parts_Common_Owner="/AsideSecond:before" />
</Placement>
IMHO the best way to have a simple extension on an Orchard user, is to create a ContentPart, e.g. "UserExtensions", and attach it to the Orchard user.
This UserExtensions part can then hold your fields, etc.
This way, your extensions are clearly separated from the core user.
To access this part and its fields in the front-end, just add an alternate for the particular view you want to override.
Is there a way to pass through fields on the User shape in a blog post?
Do you want to display a nice picture / vita / whatever of the blog posts author? If so:
This could be your Content-BlogPost.Detail.cshtml - Alternate
#using Orchard.Blogs.Models
#using Orchard.MediaLibrary.Fields
#using Orchard.Users.Models
#using Orchard.Utility.Extensions
#{
// Standard Orchard stuff here...
if ( Model.Title != null )
{
Layout.Title = Model.Title;
}
Model.Classes.Add("content-item");
var contentTypeClassName = ( (string)Model.ContentItem.ContentType ).HtmlClassify();
Model.Classes.Add(contentTypeClassName);
var tag = Tag(Model, "article");
// And here we go:
// Get the blogPost
var blogPostPart = (BlogPostPart)Model.ContentItem.BlogPostPart;
// Either access the creator directly
var blogPostAuthor = blogPostPart.Creator;
// Or go this way
var blogPostAuthorAsUserPart = ( (dynamic)blogPostPart.ContentItem ).UserPart as UserPart;
// Access your UserExtensions part
var userExtensions = ( (dynamic)blogPostAuthor.ContentItem ).UserExtensions;
// profit
var profilePicture = (MediaLibraryPickerField)userExtensions.ProfilePicture;
}
#tag.StartElement
<header>
#Display(Model.Header)
#if ( Model.Meta != null )
{
<div class="metadata">
#Display(Model.Meta)
</div>
}
<div class="author">
<img src="#profilePicture.FirstMediaUrl"/>
</div>
</header>
#Display(Model.Content)
#if ( Model.Footer != null )
{
<footer>
#Display(Model.Footer)
</footer>
}
#tag.EndElement
Hope this helps, here's the proof:

liferay change page title dynamically

I'm trying to change the title of the page, but the method PortalUtil.setPageTitle("title", request); is not working from the jsp. I also tried in the doView method.
My second attempt was throught servletrequest:
In doView I wrote
HttpServletRequest httpRequest = PortalUtil.getOriginalServletRequest(PortalUtil.getHttpServletRequest(renderRequest));
httpRequest.setAttribute("hola", "hola");
And in the portal normal I tried with:
#set ($holas =$request.get('attributes').get('hola'))
#set ($holas2 = $request.getSession().getAttribute("hola"))
$holas
$holas2
but Velocity only shows $holas $holas2.
Looks like I got it wrong in my first attempt - thus I've replaced the previous answer with this one: Add this code to your JSP or doView:
<%
com.liferay.portal.util.PortalUtil.setPageTitle("Honk", request);
%>
In your jsp you should try
<%
layout.setTitle("title");
%>
layout is an Layout object generated by jsp.
Use below code,
String title = (String)renderRequest.getAttribute("title");
HtmlPageTitleUtil.setHtmlTitle(title, request, true);
Pass title attribute from the controller or you can use static text as well.
Import the above utility class as well as,
<portlet:defineObjects />
<theme:defineObjects />
this to jsp and its done.

Orchard Alternate Shape Template Not Displaying Values

I'm new to Orchard and have watched both the Pluralsight "Orchard Fundamentals" and "Advanced Orchard" tutorials. Its a great platform, but I'm having a hard time wrapping my head around a couple of things.
I'd like to create a blog showcase banner on the home page only that rotates blog posts on the site. I have the HTML sliced up and functioning on an HTML template. The banner looks like this:
http://arerra.com/news-slideshow.jpg
So far I have done the following:
I've created a Blog called "Articles" and have placed a single post in there for testing.
Added a Layer called "ArticleList" where I have placed a Widget for "Recent Blog Posts"
I've created a custom layout for the home page called "Layout-Url-HomePage.cshtml" in my theme.
In my Theme "Views" folder, I have created a file called "Widget.Wrapper.cshtml" with only #Display(Model.Child) in it to remove the <article><header/><footer /><article> tags globally from the widgets.
Added a file in "Views > Parts > Blogs.RecentBlogPosts.cshtml" to control the layout of my shape. The code is the following:
#using Orchard.ContentManagement;
#{
IEnumerable<object> blogPosts = Model.ContentItems.ContentItems;
}
#if (blogPosts != null) {
<div class="container news-slider">
<ul class="slide-images">
#foreach (dynamic post in blogPosts) {
string title = post.Title;
ContentItem item = post.ContentItem;
<img src="/Themes/MountainWestHoops/Content/img/placeholder-700x380.jpg" alt="#title" class="active" />
}
</ul>
#foreach (dynamic post in blogPosts) {
string title = post.Title;
string body = post.Body;
ContentItem item = post.ContentItem;
<div class="featured-story threeD active">
<h1>#title</h1>
<p>#body #Html.ItemDisplayLink("READ MORE", item)</p>
</div>
}
<aside>
<ul class="tabs">
#foreach (dynamic post in blogPosts) {
string title = post.Title;
string url = post.Url;
ContentItem item = post.ContentItem;
<li><h3>#title</h3></li>
}
</ul>
<div class="ad-three-day-trial">
<img src="/Themes/Content/img/placeholder-260x190.gif" />
</div>
</aside>
</div>
}
My HTML is rendering properly, but none of the values that I have specified are showing up.
I am using the "Shape Tracer" module to see what template is being used. What is funny, is that the #Html.ItemDisplayLink("READ MORE", item) is rendering the article's URL, and if I replace the "READ MORE" with the string title, the title renders properly.
What am I doing wrong here that is causing strings to not display? Am I missing a larger point and misunderstanding the fundamentals? The tutorials seems to say that you can simply move around parts, but in this case, I need to have very specific markup for this slider to work.
Seems like your source was http://weblogs.asp.net/bleroy/archive/2011/03/27/taking-over-list-rendering-in-orchard.aspx
That is a rather old post, and the way the title is handled has changed since then.
The DisplayLink works because the only correct property here is post.ContentItem, which is what that API takes. post.Title and post.Body on the other hand are very likely null, which is why you see nothing. To access the title, you can use post.ContentItem.TitlePart.Title and to get the body, post.ContentItem.BodyPart.Text.

How to get client side portlet-id in liferay?

I'm using AlloyUI in my liferay portlet.
I want to use my <input>'s id in javascript. The problem is that the id of the elements are changed in client side.
For example:
If I set an <input>'s Id to "username" it is changed to _hospital_WAR_hospitalportlet_userName i.e. _hospital_WAR_hospitalportlet_ is appended to the Id, where Hospital is my portlet name.
How can I get client-side Id so that I can use it in jquery?
The string _hospital_WAR_hospitalportlet_ prepended to the Id of the <input> is nothing but the portlet-namespace.
This is only prepended to your <input>'s name & id attribute if you use <aui:input> tag and the name & id attributes are not changed if you just use plain-vanilla html <input> tag.
But as it is a good practice to use <aui:input> you can do the following to get the portlet-namespace in your javascript code:
If you are using javascripts inside a JSP i.e. using within <script> .. </script> or <aui:script> .. </aui:script> then you can use <portlet:namespace /> or <%= renderResponse.getNamespace() %> to get the string _hospital_WAR_hospitalportlet_ inside your javascript, something like.
jQuery("#<portlet:namespace />username").val();
// Or
jQuery("#<%= renderResponse.getNamespace() %>username").val();
But if you are using a *.js file then I suggest you pass the namespace as an argument to the javascript function in the js file:
function changeValues(portletNamespace) { // this function is in a js file
jQuery("#" + portletNamespace + "username").val("Lets change");
}
calling this function from the JSP:
<input type="button" onClick="changeValues('<portlet:namespace />')" />
Hope this helps. I don't know if there is a way to get the namespace or portletId directly through some javascript function defined by Liferay. If you get something like that you can post it here and that would be very helpful.
Try this:
Liferay.Portlet.ready(
/*
This function gets loaded after each and every portlet on the page.
portletId: the current portlet's id
node: the Alloy Node object of the current portlet
*/
function(portletId, node) {
}
);

Resources