Fork me on GitHub
2sxc Learn Razor
DotNetNuke tools to create, design and animate great content
You are here: Home  >  Parent-Child

Parent-Child Demo

The following table shows a list of items. The links in each row demonstrate various way to show details of this item. The exact links are explained below. 

List of People

Person InPage & nice JS Lightbox Crawlable Lightbox SEO Lightbox naked HTML
Daniel Mettler InPage, nice, details Lightbox Crawl 1, 2 SEO Lightbox naked for ajax
Benjamin Gemperle InPage, nice, details Lightbox Crawl 1, 2 SEO Lightbox naked for ajax
Raphael Müller InPage, nice, details Lightbox Crawl 1, 2 SEO Lightbox naked for ajax
 

Explaining the links

  • InPage shows a normal link, opening in the same page. It actually calls up the same page with a parameter.
  • InPage nice uses the DNN-Link Generator to create a link using the activated friendly-url provider. The result differs in each installation
  • InPage details uses the DNN-Link Generator and hides all other modules (by specifying mid=CurrentModule). You will notice that Look-Inside is missing, because it's another module.
  • JS Lightbox shows a dnn-lightbox with a practical url. Usually lightbox-urls don't need to be nice, because google should index a page with more layout and skip the lightbox
  • Crawlable Lightbox 1 actually has a normal link with layout, but caches the click and shows a lightbox to the user - this is the better of doing things...
  • Crawlable Lightbox 2 is the same as #2, but with a nice, friendly-URL
  • SEO Lightbox is the same again, but now adds the title of the element into the URL for a perfect, SEO-friendly crawlable page. Note that we applied another trick: we didn't go /title/daniel-mettler/ but the other way around /daniel-mettler/title/. This is just to place the keyword-stuffing as early as possible. DNN doesn't care, it just needs pairs of values to put into the URL. 
  • Naked HTML for AJAX is a even more reduced output without the <html><body> stuff around it. You would use this for AJAX-Lightboxes or for inline AJAX. 

Explaining the Lightbox

For simplicity I'm using the built-in DNN-Lightbox. The documentation is found here. The most important things you must know...

  1. First parameter: URL to open
  2. Second: show "Return" button
  3. height of window
  4. width of window
  5. true/false: reload parent page when closing lightbox
  6. optional redirect-after close (not needed in parent/child scenarios)

Note that we (2sic) usually use other lightboxes because they are nicer, offer more features and because we're keen on designing it just right. So we're just demoing this because we're sure it will work on your DNN. 

Look inside

Content Item

These are the values a content-editor can manage.
Name Type Value
FullName System.String Daniel Mettler
Website System.String http://www.2sic.com/dm
Photo System.String /learn-razor/Content/Authors/Daniel.jpg


Presentation Item

These are additional, optional presentation instructions a content-editor can manage. If none are entered, a default set (predefined by the designer) will be used.

No Presentation parameters specified, using default presentation for this item.


Template file

@using System.Text
@using System.Text.RegularExpressions

@{
	// get view name from URL or default to "list"
    var viewName = Request.QueryString["view"];
    if(viewName == null) {
        viewName = "List";
    }
    viewName = viewName.ToLower();

	// get details-ID from URL or default to 0 (zero)
    var detailsId = 0; 
    int.TryParse(Request.QueryString["id"], out detailsId);
}

@* Default view (list) *@
@if(viewName == "list") {
	<h2>List of People</h2>
    <table width="100%" border="1">
		<tr>
			<td>Person</td>
			<td>InPage & nice</td>
			<td>JS Lightbox</td>
			<td>Crawlable Lightbox</td>
			<td>SEO Lightbox</td>
			<td>naked HTML</td>
		</tr>
    @foreach(var e in List) {
    	// get the content entity (not the presentation)
    	var Content = e.Content;
		<tr>
			<td>@Content.FullName</td>
			<td>
				<a href="?view=details&id=@Content.EntityId">InPage</a>,
				<a href="@DotNetNuke.Common.Globals.NavigateURL(Dnn.Tab.TabID, "", "view=details&id=" + Content.EntityId.ToString())">nice</a>,
				<a href="@DotNetNuke.Common.Globals.NavigateURL(Dnn.Tab.TabID, "", "view=details&id=" + Content.EntityId.ToString() + "&mid=" + Dnn.Module.ModuleID)">details</a>
			</td>
			<td>
				<a href="javascript:dnnModal.show('?mid=@Dnn.Module.ModuleID&view=details&id=@Content.EntityId&popUp=true', false,360,500,false,'')">Lightbox</a>
			</td>
			<td>
				<a href="?view=details&id=@Content.EntityId" onclick="dnnModal.show(this.href + '&mid=@Dnn.Module.ModuleID&&popUp=true', false,360,500,false,''); return false;">Crawl 1</a>,
				<a href="@DotNetNuke.Common.Globals.NavigateURL(Dnn.Tab.TabID, "", "view=details&id=" + Content.EntityId.ToString())" onclick="dnnModal.show(this.href + '?mid=@Dnn.Module.ModuleID&&popUp=true', false,360,500,false,''); return false;">2</a>
			</td>
			<td>
				<a href="@DotNetNuke.Common.Globals.NavigateURL(Dnn.Tab.TabID, "", ToSeoFriendly(Content.FullName, 250) + "=title&"
				+ "&view=details&id=" + Content.EntityId.ToString())" onclick="dnnModal.show(this.href + '?mid=@Dnn.Module.ModuleID&&popUp=true', false,360,500,false,''); return false;">SEO Lightbox</a>
			</td>
			<td>
				<a href="@DotNetNuke.Common.Globals.NavigateURL(Dnn.Tab.TabID, "", "view=details&id=" + Content.EntityId.ToString() + "&popUp=true&standalone=true")">naked for ajax</a>
			</td>
		</tr>
	}
	</table>
	<div>&nbsp;</div>
}

@* Details view (details) *@
@if(viewName == "details") {
    // var foundElement = List.Where(e => e.Content.EntityId == detailsId).FirstOrDefault();
    var foundElement = Data.List.Where(e => e.EntityId == detailsId).FirstOrDefault();
    if(foundElement != null) {
		// get the content entity (not the presentation)
        var details = AsDynamic(foundElement);//.Content;
        <h2>Details</h2>

		// Here's some special stuff necessary to find all courses referring to this author
		// 1. leave the simple API, go to the power API of entities, must be typed to work
		ToSic.Eav.Interfaces.IEntity ent = AsEntity(details);
		
		// 2. Get all incomming relationships (all parents)
		var entitiesReferringToThis = ent.Relationships.AllParents;
		
		// 3. Filter all parents, we only want the courses (and not books, etc.)
		var Courses = entitiesReferringToThis.Where(c => c.Type.Name == "Courses");
		
		<div class="sc-element">
		  @Edit.Toolbar(details)
		  <img src="@details.Photo?w=200&h=200&mode=crop" style="float:left">
		  <div style="height: 220px">
				<h3>@details.FullName</h3>
				<p>Visit his website <a href="@details.Website" target="_blank">here</a></p>
				@if(Courses.Any()) {
					<p>
					<strong>Courses by @details.FullName</strong><br>
					<ol>
						@foreach (var course in Courses) 
						{
							var c = AsDynamic(course);
							<li>@c.Title</li>
						}
					</ol>
					</p>
				}
		  </div>
		</div>



	} else {
        <h3>Error: Author with ID @detailsId not found </h3>
    }
}

@functions{
	// helper function to create nice url-title
	// found this here: http://stackoverflow.com/questions/465659/how-can-i-create-a-seo-friendly-dash-delimited-url-from-a-string?rq=1
	private string ToSeoFriendly(string title, int maxLength) {
		var match = Regex.Match(title.ToLower(), "[\\w]+");
		StringBuilder result = new StringBuilder("");
		bool maxLengthHit = false;
		while (match.Success && !maxLengthHit) {
			if (result.Length + match.Value.Length <= maxLength) {
				result.Append(match.Value + "-");
			} else {
				maxLengthHit = true;
				// Handle a situation where there is only one word and it is greater than the max length.
				if (result.Length == 0) result.Append(match.Value.Substring(0, maxLength));
			}
			match = match.NextMatch();
		}
		// Remove trailing '-'
		if (result[result.Length - 1] == '-') result.Remove(result.Length - 1, 1);
		return result.ToString();
	}
}
2serve . 2invent . 2create is 2be.