Is it possible to load a specific 2sxc module in a DNN skin? - razor

DNN Platform 9.3.2 /
2sxc 10.25.2
I have a DNN website that uses 2sxc. I created a "Notification Bar" content type and c# razor template that I use to display special notifications to the user. This module is meant to display on every single page of the website. I used the "Add Existing Module" functionality to manually add the module to every page but it's a bit cumbersome and I run the risk that my Content Editors move the module by accident, delete, or forget to add it to new pages.
Is there a special 2sxc skin object that I can use inside of my .ascx DNN skin to load a 2sxc module so that I don't have to add it to every page through DNN? Apparently there is one in DNN OpenContent.
(More than just the notification bar, this would be super useful for the site's header or footer that gets occasionally updated. For example, social media links, contact info like address or phone number, or other links that aren't part of the DNN pages menu.)

There are two ways
create a pane for this specific module (it's the easiest to edit and work with) and just show the module on all pages
create the module on a hidden page and then inject it into the skin, using the Factory to get the CmsBlock - see https://docs.2sxc.org/api/dot-net/ToSic.Sxc.Dnn.Factory.html#ToSic_Sxc_Dnn_Factory_CmsBlock_System_Int32_System_Int32_

Daniel, this is how we did it in the past. I notice your call is similar but simpler (above in the comments). Is that because the API changed somewhere after v10?
<script runat="server">
// get 2sxc to Render() the output from the module on the SITE/Manage Flyout Links page
private IHtmlString RenderFlyoutMenu()
{
return ToSic.SexyContent.Environment.Dnn7.Factory.SxcInstanceForModule(3354, 606).Render();
}
</script>
<%=RenderFlyoutMenu() %>

Related

Is it possible to make a Razor Tag Helper to show/hide content wrapped in it under certain server side conditions

As per the title really, but to give it more specifics:
My web app has multiple users, each has a different set of permissions and this means that certain parts of the app aren't available to them, in most cases this is simple, whole sections are just blocked out and not displayed at all, but in some cases I would like to be able to wrap a certain section of a page in a tag which if the user hasn't permission to see will either hide this section entirely, or show a "you don't have permission to use this bit" partial view.
I am using .NET Core 3.1 and Razor Pages.
So I am thinking something like this:
<html>
<body>
My web page content....
<permission requires="view_invoices">
<h3>Invoices</h3>
.... invoice content....
BUT - if user has not got permission this section is skipped, so is blank, or shows (/Views/Partial/PermissionNotAvailable)
</permission>
</body>
</html>
Edit - for clarity, I want to be able to write my content assuming the user has permission to view it, but if they don't, the fact that it is wrapped in the permissions tag helper will have it removed or replaced by a server-side helper.
If you are using ASP.NET authorization and razor pages you can do something like the following:
#if (User.IsInRole("ViewInvoices")) {
<h3>Invoices</h3>
.... invoice content....
} else {
(/Views/Partial/PermissionNotAvailable)
}
Where ViewInvoices is a role you added to the database and assigned to certain users. If the user does not have this role that section of the page is not returned to the client.

How do I generate SEO-friendly markup for a single-page web app? [duplicate]

There are a lot of cool tools for making powerful "single-page" JavaScript websites nowadays. In my opinion, this is done right by letting the server act as an API (and nothing more) and letting the client handle all of the HTML generation stuff. The problem with this "pattern" is the lack of search engine support. I can think of two solutions:
When the user enters the website, let the server render the page exactly as the client would upon navigation. So if I go to http://example.com/my_path directly the server would render the same thing as the client would if I go to /my_path through pushState.
Let the server provide a special website only for the search engine bots. If a normal user visits http://example.com/my_path the server should give him a JavaScript heavy version of the website. But if the Google bot visits, the server should give it some minimal HTML with the content I want Google to index.
The first solution is discussed further here. I have been working on a website doing this and it's not a very nice experience. It's not DRY and in my case I had to use two different template engines for the client and the server.
I think I have seen the second solution for some good ol' Flash websites. I like this approach much more than the first one and with the right tool on the server it could be done quite painlessly.
So what I'm really wondering is the following:
Can you think of any better solution?
What are the disadvantages with the second solution? If Google in some way finds out that I'm not serving the exact same content for the Google bot as a regular user, would I then be punished in the search results?
While #2 might be "easier" for you as a developer, it only provides search engine crawling. And yes, if Google finds out your serving different content, you might be penalized (I'm not an expert on that, but I have heard of it happening).
Both SEO and accessibility (not just for disabled person, but accessibility via mobile devices, touch screen devices, and other non-standard computing / internet enabled platforms) both have a similar underlying philosophy: semantically rich markup that is "accessible" (i.e. can be accessed, viewed, read, processed, or otherwise used) to all these different browsers. A screen reader, a search engine crawler or a user with JavaScript enabled, should all be able to use/index/understand your site's core functionality without issue.
pushState does not add to this burden, in my experience. It only brings what used to be an afterthought and "if we have time" to the forefront of web development.
What your describe in option #1 is usually the best way to go - but, like other accessibility and SEO issues, doing this with pushState in a JavaScript-heavy app requires up-front planning or it will become a significant burden. It should be baked in to the page and application architecture from the start - retrofitting is painful and will cause more duplication than is necessary.
I've been working with pushState and SEO recently for a couple of different application, and I found what I think is a good approach. It basically follows your item #1, but accounts for not duplicating html / templates.
Most of the info can be found in these two blog posts:
http://lostechies.com/derickbailey/2011/09/06/test-driving-backbone-views-with-jquery-templates-the-jasmine-gem-and-jasmine-jquery/
and
http://lostechies.com/derickbailey/2011/06/22/rendering-a-rails-partial-as-a-jquery-template/
The gist of it is that I use ERB or HAML templates (running Ruby on Rails, Sinatra, etc) for my server side render and to create the client side templates that Backbone can use, as well as for my Jasmine JavaScript specs. This cuts out the duplication of markup between the server side and the client side.
From there, you need to take a few additional steps to have your JavaScript work with the HTML that is rendered by the server - true progressive enhancement; taking the semantic markup that got delivered and enhancing it with JavaScript.
For example, i'm building an image gallery application with pushState. If you request /images/1 from the server, it will render the entire image gallery on the server and send all of the HTML, CSS and JavaScript down to your browser. If you have JavaScript disabled, it will work perfectly fine. Every action you take will request a different URL from the server and the server will render all of the markup for your browser. If you have JavaScript enabled, though, the JavaScript will pick up the already rendered HTML along with a few variables generated by the server and take over from there.
Here's an example:
<form id="foo">
Name: <input id="name"><button id="say">Say My Name!</button>
</form>
After the server renders this, the JavaScript would pick it up (using a Backbone.js view in this example)
FooView = Backbone.View.extend({
events: {
"change #name": "setName",
"click #say": "sayName"
},
setName: function(e){
var name = $(e.currentTarget).val();
this.model.set({name: name});
},
sayName: function(e){
e.preventDefault();
var name = this.model.get("name");
alert("Hello " + name);
},
render: function(){
// do some rendering here, for when this is just running JavaScript
}
});
$(function(){
var model = new MyModel();
var view = new FooView({
model: model,
el: $("#foo")
});
});
This is a very simple example, but I think it gets the point across.
When I instante the view after the page loads, I'm providing the existing content of the form that was rendered by the server, to the view instance as the el for the view. I am not calling render or having the view generate an el for me, when the first view is loaded. I have a render method available for after the view is up and running and the page is all JavaScript. This lets me re-render the view later if I need to.
Clicking the "Say My Name" button with JavaScript enabled will cause an alert box. Without JavaScript, it would post back to the server and the server could render the name to an html element somewhere.
Edit
Consider a more complex example, where you have a list that needs to be attached (from the comments below this)
Say you have a list of users in a <ul> tag. This list was rendered by the server when the browser made a request, and the result looks something like:
<ul id="user-list">
<li data-id="1">Bob
<li data-id="2">Mary
<li data-id="3">Frank
<li data-id="4">Jane
</ul>
Now you need to loop through this list and attach a Backbone view and model to each of the <li> items. With the use of the data-id attribute, you can find the model that each tag comes from easily. You'll then need a collection view and item view that is smart enough to attach itself to this html.
UserListView = Backbone.View.extend({
attach: function(){
this.el = $("#user-list");
this.$("li").each(function(index){
var userEl = $(this);
var id = userEl.attr("data-id");
var user = this.collection.get(id);
new UserView({
model: user,
el: userEl
});
});
}
});
UserView = Backbone.View.extend({
initialize: function(){
this.model.bind("change:name", this.updateName, this);
},
updateName: function(model, val){
this.el.text(val);
}
});
var userData = {...};
var userList = new UserCollection(userData);
var userListView = new UserListView({collection: userList});
userListView.attach();
In this example, the UserListView will loop through all of the <li> tags and attach a view object with the correct model for each one. it sets up an event handler for the model's name change event and updates the displayed text of the element when a change occurs.
This kind of process, to take the html that the server rendered and have my JavaScript take over and run it, is a great way to get things rolling for SEO, Accessibility, and pushState support.
Hope that helps.
I think you need this: http://code.google.com/web/ajaxcrawling/
You can also install a special backend that "renders" your page by running javascript on the server, and then serves that to google.
Combine both things and you have a solution without programming things twice. (As long as your app is fully controllable via anchor fragments.)
So, it seem that the main concern is being DRY
If you're using pushState have your server send the same exact code for all urls (that don't contain a file extension to serve images, etc.) "/mydir/myfile", "/myotherdir/myotherfile" or root "/" -- all requests receive the same exact code. You need to have some kind url rewrite engine. You can also serve a tiny bit of html and the rest can come from your CDN (using require.js to manage dependencies -- see https://stackoverflow.com/a/13813102/1595913).
(test the link's validity by converting the link to your url scheme and testing against existence of content by querying a static or a dynamic source. if it's not valid send a 404 response.)
When the request is not from a google bot, you just process normally.
If the request is from a google bot, you use phantom.js -- headless webkit browser ("A headless browser is simply a full-featured web browser with no visual interface.") to render html and javascript on the server and send the google bot the resulting html. As the bot parses the html it can hit your other "pushState" links /somepage on the server mylink, the server rewrites url to your application file, loads it in phantom.js and the resulting html is sent to the bot, and so on...
For your html I'm assuming you're using normal links with some kind of hijacking (e.g. using with backbone.js https://stackoverflow.com/a/9331734/1595913)
To avoid confusion with any links separate your api code that serves json into a separate subdomain, e.g. api.mysite.com
To improve performance you can pre-process your site pages for search engines ahead of time during off hours by creating static versions of the pages using the same mechanism with phantom.js and consequently serve the static pages to google bots. Preprocessing can be done with some simple app that can parse <a> tags. In this case handling 404 is easier since you can simply check for the existence of the static file with a name that contains url path.
If you use #! hash bang syntax for your site links a similar scenario applies, except that the rewrite url server engine would look out for _escaped_fragment_ in the url and would format the url to your url scheme.
There are a couple of integrations of node.js with phantom.js on github and you can use node.js as the web server to produce html output.
Here are a couple of examples using phantom.js for seo:
http://backbonetutorials.com/seo-for-single-page-apps/
http://thedigitalself.com/blog/seo-and-javascript-with-phantomjs-server-side-rendering
If you're using Rails, try poirot. It's a gem that makes it dead simple to reuse mustache or handlebars templates client and server side.
Create a file in your views like _some_thingy.html.mustache.
Render server side:
<%= render :partial => 'some_thingy', object: my_model %>
Put the template your head for client side use:
<%= template_include_tag 'some_thingy' %>
Rendre client side:
html = poirot.someThingy(my_model)
To take a slightly different angle, your second solution would be the correct one in terms of accessibility...you would be providing alternative content to users who cannot use javascript (those with screen readers, etc.).
This would automatically add the benefits of SEO and, in my opinion, would not be seen as a 'naughty' technique by Google.
Interesting. I have been searching around for viable solutions but it seems to be quite problematic.
I was actually leaning more towards your 2nd approach:
Let the server provide a special website only for the search engine
bots. If a normal user visits http://example.com/my_path the server
should give him a JavaScript heavy version of the website. But if the
Google bot visits, the server should give it some minimal HTML with
the content I want Google to index.
Here's my take on solving the problem. Although it is not confirmed to work, it might provide some insight or idea's for other developers.
Assume you're using a JS framework that supports "push state" functionality, and your backend framework is Ruby on Rails. You have a simple blog site and you would like search engines to index all your article index and show pages.
Let's say you have your routes set up like this:
resources :articles
match "*path", "main#index"
Ensure that every server-side controller renders the same template that your client-side framework requires to run (html/css/javascript/etc). If none of the controllers are matched in the request (in this example we only have a RESTful set of actions for the ArticlesController), then just match anything else and just render the template and let the client-side framework handle the routing. The only difference between hitting a controller and hitting the wildcard matcher would be the ability to render content based on the URL that was requested to JavaScript-disabled devices.
From what I understand it is a bad idea to render content that isn't visible to browsers. So when Google indexes it, people go through Google to visit a given page and there isn't any content, then you're probably going to be penalised. What comes to mind is that you render content in a div node that you display: none in CSS.
However, I'm pretty sure it doesn't matter if you simply do this:
<div id="no-js">
<h1><%= #article.title %></h1>
<p><%= #article.description %></p>
<p><%= #article.content %></p>
</div>
And then using JavaScript, which doesn't get run when a JavaScript-disabled device opens the page:
$("#no-js").remove() # jQuery
This way, for Google, and for anyone with JavaScript-disabled devices, they would see the raw/static content. So the content is physically there and is visible to anyone with JavaScript-disabled devices.
But, when a user visits the same page and actually has JavaScript enabled, the #no-js node will be removed so it doesn't clutter up your application. Then your client-side framework will handle the request through it's router and display what a user should see when JavaScript is enabled.
I think this might be a valid and fairly easy technique to use. Although that might depend on the complexity of your website/application.
Though, please correct me if it isn't. Just thought I'd share my thoughts.
Use NodeJS on the serverside, browserify your clientside code and route each http-request's(except for static http resources) uri through a serverside client to provide the first 'bootsnap'(a snapshot of the page it's state). Use something like jsdom to handle jquery dom-ops on the server. After the bootsnap returned, setup the websocket connection. Probably best to differentiate between a websocket client and a serverside client by making some kind of a wrapper connection on the clientside(serverside client can directly communicate with the server). I've been working on something like this: https://github.com/jvanveen/rnet/
Use Google Closure Template to render pages. It compiles to javascript or java, so it is easy to render the page either on the client or server side. On the first encounter with every client, render the html and add javascript as link in header. Crawler will read the html only but the browser will execute your script. All subsequent requests from the browser could be done in against the api to minimize the traffic.
This might help you : https://github.com/sharjeel619/SPA-SEO
Logic
A browser requests your single page application from the server,
which is going to be loaded from a single index.html file.
You program some intermediary server code which intercepts the client
request and differentiates whether the request came from a browser or
some social crawler bot.
If the request came from some crawler bot, make an API call to
your back-end server, gather the data you need, fill in that data to
html meta tags and return those tags in string format back to the
client.
If the request didn't come from some crawler bot, then simply
return the index.html file from the build or dist folder of your single page
application.

Template Editor AEM not working as expected

We are using template editor in AEM 6.2 to create templates , and we have followed below steps to create a template-
1.Created page template as done in we-retail site.
2.Create empty page template using above page template.
3.Created template using empty page template.
Did following modifications on top of we retail page component as per our requirement-
As we need to have header and footer as full width parsys i.e 1340 width and body as 940 width-
.site-wrapper {
width:1340px;
}
.container {
width:940px;
}
So we did following modifications in /apps//components/structure/page/partials/body.html -
<div class="site-wrapper">
<div data-sly-resource="${ # path='header', resourceType='/apps/<projectname>/components/structure/header'}"
data-sly-unwrap>
</div>
</div>
<div class="container"
data-sly-use.templatedContainer="com.day.cq.wcm.foundation.TemplatedContainer">
<sly data-sly-repeat="${templatedContainer.structureResources}"
data-sly-resource="${item.path # resourceType=item.resourceType, decorationTagName='div'}" />
</div>
<div class="site-wrapper">
<div data-sly-resource="${ # path='footer', resourceType='/apps/<projectname>/components/structure/footer'}" data-sly-unwrap></div>
</div>
Also we have few more components which will take full width on the page so i have added responsivegrid component under full width div.
But i am not able to edit the header and footer component in template as they are not under templateresource.
Also even if i add design dialog under header and footer i am not able to edit those components directly on the page in design mode even if they are unlocked.
Please let me know if i am doing anything wrong here or we cant customize body.html as in we-retail site.
I thought of using different parsys for full width and for body.
And i don't want to control using css as i have multiple components which are full width.
Regards
Ankur
First, the objective of the Template Editor is precisely to not do any static includes like what you edited on your page component, because the Template Editor now provides a UI to include such components on the page level, allowing to define which included components can be edited or not by authors on the resultant pages. That way, if some page suddenly requires another header or footer, this can be edited through the UI of the Template Editor and doesn't require a development cycle.
So I'd recommend to remove your edits of the body.html, and rather make sure that your Header and Footer components are editable: meaning that the cq:Component node must have a title (jcr:title), a group (componentGroup), as well as an cq:editConfig, a classic dialog or a classic design dialog (in 6.2 and before, the classic dialogs were still needed to make a component editable, but this won't be the case anymore for future versions, where touch dialogs can be provided instead).
Once you're there, here are detailed instructions for setting up your site with the Template Editor UI in AEM 6.2:
Create the template
For now, we'll create the template in the global folder, later however you'll have to make sure that the chosen folder is specific to your site.
Go to the Template Editor (in AEM's global nav, select General > Templates).
Pick the global folder (or your site-specific folder).
Hit the "Create" button and choose "HTML5 Page", hit "Next" and give your template a name, like "Simple Page", then hit "Create" and choose "Open".
Add Client Libraries
Let's configure the page component to load the CSS and JS client libraries that are needed for our site.
In "Structure" mode of the Template Editor, select the second icon from the top-left ("Page Information") and choose "Page Policy". A policy is basically a reusable design configuration that can be shared and reused across multiple templates if desired. What we'll do is duplicate that policy and then edit it to instruct the page to load additional client libraries.
In the "Policy" dialog, duplicate the "Default Page" policy with the double-arrow icon and rename it for instance to " Config". Then click the checkmark at the top-right of the dialog to save.
Again in the top-left ("Page Information") menu, choose this time "Page Design" to edit the actual design configuration.
Edit the list to include all client libraries required by the components that you plan to use. If the template author isn't a developer, this is typically where the developer must instruct the template author what clientlibs must be loaded on the pages of a specific site. In case you have We.Retail installed, you can add a field and paste we-retail.base into it. Save by clicking the top-right checkmark.
Add Structure Components
Structure components are those that were usually hard-coded through static includes on the page components. We typically don't want the structure components to be editable by our page authors later on, unless explicitly defined.
On the page, select the empty parsys and in its toolbar, choose the 1st icon ("Policy") to edit policy.
In the "Policy" dialog, duplicate the "Default Layout Container" policy and rename it for instance to "Template Config". This will be the name of the configuration that tells what components are available in the template for that page-level layout container. Save.
As the page reloads, select the empty parsys again, and this time choose the 2nd icon ("Design") to edit the design configuration.
In the design dialog that opens, select all the components that you want to have available in the template editor (for example, in addition to the few General components already selected, also select the "We.Retail" and the "We.Retail.Structure" component groups at the bottom of the list, or the group name you assigned to your components with the componentGroup property). Make sure to have also the "Layout Container" component selected, as this is the paragraph system (aka parsys) that we'll require later to make the page editable. Save.
You should now see your components showing up in the left "Components" rail, which allows to drag & drop your header and footer components to the page (for We.Retail the header is named "We.Retail Page Header" and is at the very bottom of the component list, and it is similar for the footer).
Also drag a "Layout Container" component between your header and footer components, which is the actual parsys that we'll make editable for our page authors. So on your page, you should now at least have following components: your header (e.g. "We.Retail Page Header"), a "Layout Container", and your footer (e.g. "We.Retail Page Footer").
Make the template editable
We now have to specify which of the components added we want page authors to be able to edit.
Select the parsys placeholder that appears between the header and the footer, and click the last icon of the toolbar ("Unlock structure component").
Once this is done, the placeholder says "No allowed components for Layout Container", the reason is that this parsys has no policy yet assigned to define the list of allowed components for the page authors. Therefore, select this parsys placeholder again and from the toolbar select the second icon ("Policy").
To base our policy on the one previously edited, select the "Template Config", and the hit the duplicate icon and rename it to "Page Config". Save.
The list of allowed components now appear below the parsys placeholder, which looks good, except that we want to remove the components that we want available in for the template structure only. Therefore, let's select the placeholder once more and select the 3rd icon ("Design") from the toolbar.
In the design dialog, uncheck the structure-specific components and groups (for e.g. uncheck the "We.Retail.Structure" group). Save.
Use the template
That's it, we can now enable the template and use it on a site.
On the template admin (which should be still open in a previous browser tab), select your newly created template and hit "Enable" and confirm "Enable".
For pages to be able to be created from templates of the folder we used, one will need to put a cq:allowedTemplates property on a parent page (typically, this property will be set to the root page of the site). However, to create the very first root page, we'll initially just add that property to the /content node by using CRXDE Lite. So go to http://localhost:4502/crx/de/index.jsp#/content and on the root content node set cq:allowedTemplates multi-String property that equals to "/conf/global/settings/wcm/templates/.*" (or whatever folder you created your template in).
Save.
Back in AEM open the global menu and go to Sites and on the root folder, click "Create" and choose "Page".
Choose our "Simple Page" template, hit "Next", give the page a title, like "My Site" and click "Create" and "Open".
You should now see the page with the defined header and footer, but only the parsys in between that is editable. Also the desired components should show up in the left rail under the second "Components" tab.
Create a Template Type
In order to avoid having to repeat all these steps (mainly 1-18) each time one wants to create a new template, we can create a template type out of the template that we created.
In CRXDE Lite, go to the folder where you've created your template, like /conf/global/settings/wcm/templates and copy the template that should become a template type, like the simple-page node in our case.
Move to the template-types folder (e.g. /conf/global/settings/wcm/template-types in our case) and paste there the copied node.
Save.
Now, when creating a template in the global folder, one can choose the "Simple Page" as a starting point.
As you can see, the Template Editor introduces a very big change, not only technically, but also in the process: what required development steps can now be achieved through configuration. I'd therefore recommend to edit the page component only to adapt the technical HTML headers, but not to hard-code any visual items that should be displayed on the page, because surely enough in a few months/years the visual items will change and multiple variations of them will be required, for which you want to lighten the development need to allow faster changes.
Also helpful are following links:
https://docs.adobe.com/docs/en/aem/6-2/develop/templates/page-templates-editable.html
http://fr.slideshare.net/PatrickFauchre/empower-template-authors
https://github.com/Adobe-Marketing-Cloud/aem-sites-example-custom-template-type
If you will check the resources included in template using calls such as <div data-sly-resource="${ # path='footer', resourceType='/apps/<projectname>/components/structure/footer'}" data-sly-unwrap></div> tends to be problematic when it comes to editing, reason so far I have figured out it that if the nodes for the resources don't exist, these resources are not editable. Refer to an article around it here.
What we did was to create a scripts to create nodes on page load (EmbeddedComponent.js) -
"use strict";
/**
* Creates a component node with name, if node does not yet exist.
*/
use([], function () {
var newResourceName = this.name;
var newResourceType = this.type;
var resourceResolver = resource.getResourceResolver();
var newNodePath = resource.path + "/" + newResourceName;
var existingComponentResource = resourceResolver.getResource(newNodePath);
if (existingComponentResource == null) {
var properties = {
"jcr:primaryType": "nt:unstructured",
"sling:resourceType": newResourceType
};
resourceResolver.create(resource, newResourceName, properties);
resourceResolver.commit();
}
});
And in you HTML script you could do something like -
<div data-sly-use="${'Path to script/EmbeddedComponent.js' # name='header', type=resTypHeader}"
data-sly-resource="<header resource type>">
have you tried the data-sly-unwrap="${!wcmmode.edit}" on the header and footer include script?

Django code to open sepecific tab in render_to_response in view

In my Django code I want to implement the following flow:
After submitting a Html form to view
Redirect to next tab in same HTML form which contain next form.
This is my code so far:
def addnewroute(request):
if request.method == "POST":
# do needed
render_to_response('useradd.html')
Introduction
Tabs are usually a visual (UI) element; meaning that there are CSS styles defining the actual tabs as "pressed" or "depressed". How the tabs "change" is defined by the implementation method you choose. Let's look at the simplest solutions.
Manual render (hard code / multi template)
If you prefer to build it all manually, you can add a condition to choose the correct html template, which would already be pre-styled to the correct tab pressed, and display the required content. I would not recommend this method except to learn more of how the internals work and as proof of concept.
def addnewroute(request):
# ...
if step1:
return render_to_response('useradd-tab1.html')
if step2:
return render_to_response('useradd-tab2.html')
Context / Template reuse
If you prefer to reuse most of your template content you can utilize the context dictionary argument to pass a step variable (to define in "which tab you should be now"), and a content variable (containing the tab content or other switch data), into your template; which will change depending on the reached step:
def addnewroute(request):
# ...
if step1:
return render_to_response('useradd.html', {'step': 1, 'form': form1})
if step2:
return render_to_response('useradd.html', {'step': 2, 'form': form2})
Then, use the passed context variables in your template, to define the condition that toggles the selected style on the tabs and displays the relevant form.
<div id="tab1" class="tab{% if step1 %} selected{% endif %}">...</div>
{{ form.as_table }}
This method is very similar to the first, except the same template is reused for both steps.
Caveats with above direct render implementations
The above methods can accomplish what you asked about; however, there are a few caveats. First, the URL remains the same, which means the user cannot navigate between steps in a persistent manner. Second, the amount of "wiring code" you would have to write (front and back-end) will be a real labor. This is why I would recommend one of the following implementations for a "stepped form".
Form Wizard
Django (versions >= 1.4, < 1.8) shipped with an "optional “form wizard” application that splits forms across multiple Web pages". The Django Form Wizard uses a specialzed WizardView class based view to simplify multi-step form creation. Note: As of Django 1.8, The form wizard was moved out of django.contrib into it's own package django-formtools.
Javascript
A more sophisticated solution may involve Javascript activated tabs, such as bootstrap tabs. In this case you would have to either: a. render all the forms in the same template (hidden by default, toggleable by on-click events) or b. fetch the data for the forms asynchronously. The upside of this solution is a more immediate UI feel for the user, the downside is definitely more complexity.
More help
If you are new to Django, templates, tabs, etc, I would suggest implementing the solutions above from the first to the last, to better understand how the internals work; and then, how you can DRY and simplify your code.
Please note that similar questions has been asked a few times on SO, such as here, here and here. So if you have any more trouble you can try searching for a related answer.

Using multiple layout in Yii

My Yii application has a particular section called 'Edit Profile' . It's a pretty data heavy section in the way a lot of data is pulled from db for this one .
However the problem is that I have tab pagination in this section . Because only this section uses tabs on the website I did not include the related CSS/Javascript files in the main layout header .These have been referenced in the view file itself . Because of this the tabs takes time to show up and the tab titles appear as a list first (for a second or two) and then get distributed into tabs with the correct UI . This is of course unacceptable behaviour . Is there any way to selectively include related js/css files into the header tag for this particular view or should I include it in main layhout file even though it won't be used in a lot of other places on the website thus possibly slowing down other pages .
Just specify the position for the file.
In your view where you are including the js or css :
// for js
Yii::app()->clientScript->registerScriptFile('url_of_file',CClientScript::POS_HEAD);
// for css
Yii::app()->clientScript->registerCssFile('url_of_file');
Recommended documentation: registerScriptFile() , and registerCssFile()
You can create your own layout in the layouts folder , where u can include all the required jquery scripts and css. U can then call your layout in the controller.
public function actionDoSomething(){
$this->layout = 'mylayout';
$this->render('myview');
}