I have a problem about removing attributes when I navigate pages.
I used PartialView in HomeController to define index.cshtml page.
The line which I pass the data to the destination is showed orderly.
HomeController -> Contract.cshtml -> _Layout.cshtml -> NavbarPartial.cshtml
Here is HomeController.cs file shown below.
public ActionResult ContractUs()
{
ViewBag.Attribute = ""; // header-transparent
return View();
}
Here is my Contract.cshtml shown below.
#{
ViewBag.Title = "Contract Us";
Layout = "~/Views/Shared/_Layout.cshtml";
}
Here is my _Layout.cshtml shown below.
Html.RenderAction("NavbarPartial", "Home");
Here is my NavbarPartial.cshtml shown below.
<header id="header" class="fixed-top d-flex align-items-center header-transparent">
</header>
What I want to do is to show this header code snippet in the index page and show another one on another page like this shown as below without changing NavbarPartial.cshtml.
Index.cshtml
<header id="header" class="fixed-top d-flex align-items-center header-transparent">
</header>
Contract.cshtml
<header id="header" class="fixed-top d-flex align-items-center">
</header>
How can I do that?
If you render your partial view from another view, then you can send some parameters to decide what class should be applied. So let's look at the example.
We call partial view and send additional data:
#{Html.RenderPartial("_Header", new ViewDataDictionary { { "ApplyStyle", true } });}
and then in partial view we can apply style conditionally:
#{
var yourClasses = "";
if ((bool)ViewData["ApplyStyle"])
{
yourClasses = "fixed-top d-flex align-items-center header-transparent";
}
else
{
yourClasses = "fixed-top d-flex align-items-center";
}
}
<header id="header" class="#yourClasses">
This is header!
</header>
UPDATE:
This is a fiddle with complete example. However, this fiddle does not support PartialView, but I believe basic idea is shown.
Try using conditions in class value.
For example:
<header id="header" class="fixed-top d-flex align-items-center #(#Model.name === 'index' ? 'header-transparent' : '')">
If you dont have any kind of variable name for current component, you can use Javascript's location object.
window.location.pathname will provide you the pathname of current page.
Using this value you can add conditional class values
Related
I have a predicament that I am not quite sure how to overcome. I do not know what is the right way. I am building a website and I was given a template to integrate with my server code. The problem lies in how the template is outlined. Let me show you an example.
<body>
<div class="breakpoint active" id="bp_infinity" data-min-width="588">
<div id="header">full page header content</div>
<div id="body">some stuff</div>
<div id="footer">some stuff</div>
</div>
<div class="breakpoint" id="bp_587" data-min-width="493" data-max-width="587">
<div id="header">mobile header content</div>
<div id="body">some stuff</div>
<div id="footer">some stuff</div>
</div>
<div class="breakpoint" id="bp_492" data-max-width="492">
<div id="header">mobile header content</div>
<div id="body">some stuff</div>
<div id="footer">some stuff</div>
</div>
</body>
I am trying to setup my MVC5 Views in a way that does not repeats common code. The problem that I am facing is that the header and footer div are common code from page to page and the body changes. The second problem is that each page has different number of breakpoints. Here is a second page to show what I mean:
<body>
<div class="breakpoint active" id="bp_infinity" data-min-width="588">
<div id="header">full page header content</div>
<div id="body">some stuff</div>
<div id="footer">some stuff</div>
</div>
<div class="breakpoint" id="bp_587" data-max-width="587">
<div id="header">mobile header content</div>
<div id="body">some stuff</div>
<div id="footer">some stuff</div>
</div>
</body>
So the Layout page is now tricky to setup because I can't just say:
<body>
#RenderBody
</body>
One of the solutions I thought of was to use Sections, something like this:
<body>
#RenderBody
#RenderSection("Breakpoint-1", false)
#RenderSection("Breakpoint-2", false)
#RenderSection("Breakpoint-3", false)
</body>
Now each page would be along the lines of:
#section Breakpoint-1
{
<div class="breakpoint active" id="bp_infinity" data-min-width="588">
#{ Html.RenderPartial("full-page-header"); }
#{ Html.RenderPartial("full-page-body"); }
#{ Html.RenderPartial("full-page-footer"); }
</div>
}
#section Breakpoint-2
{
<div class="breakpoint" id="bp_587" data-max-width="587">
#{ Html.RenderPartial("mobile-page-header"); }
#{ Html.RenderPartial("mobile-page-body"); }
#{ Html.RenderPartial("mobile-page-footer"); }
</div>
}
A problem that I see with above code is that if the header now needs to have 5 breakpoints instead of 2, I need to go and modify it everywhere.
Is there a better way to do this? Is what I thought of the best solution for my scenario?
EDIT: To clarify. There are multiple brakpoints in the HTML because only one of them is active at a time. When page hits a certain width, 1 the currenct active breakpoint gets hidden and the new one becomes visible.
Assumptions
... are the mother of all....
"some stuff" that goes in the body tag is HTML being fed from some data source, or is hard-coded
"...the header and footer div are common code from page to page..." means that literally, you don't need to change the header/footer at all. (You still could, but I'm ignoring that for now)
The div id's "header", "body", "footer" should be handled as dom classes rather than dom ids. That is another discussion, but ids should always be unique.
Solution
This is a basic example, there are plenty of other approaches to try and plenty of other tweaks you can make
Controller
Let's call this BreakpointController
public ActionResult Index()
{
var model = new List<BreakpointViewModel>();
// populate model
return View(model);
}
ViewModel
public class BreakpointViewModel
{
public string BreakPointId { get; set; }
public int? MinWidth { get; set; }
public int? MaxWidth { get; set; }
public string Body { get; set; }
public bool IsActive { get; set; }
}
View
This should be your index.cshtml (or whatever you want to call it)
#model IEnumerable<WebApplication1.Models.BreakpointViewModel>
<div>
<h1>A header!</h1>
</div>
#Html.DisplayForModel()
<div>
<h4>A footer!</h4>
</div>
DisplayTemplate
* Thou shalt live in the folder containing views for the controller (or Shared)
* Thou shalt live in a subfolder named 'DisplayTemplates'
* Thou shalt be named {ModelName}.cshtml
in the end, the folder structure should look something like this:
Views
|-- Breakpoint
| |-- DisplayTemplates
| | +-- BreakpointViewModel.cshtml
| +-- Index.cshtml
And BreakpointViewModel.cshtml should look like this:
#model WebApplication1.Models.BreakpointViewModel
<div class="breakpoint #(Model.IsActive ? "active" : null)"
id="#Model.BreakPointId"
#(Model.MinWidth.HasValue ? "data-min-width='" + Model.MinWidth + "'" : null)
#(Model.MaxWidth.HasValue ? "data-max-width='" + Model.MaxWidth + "'" : null)>
#Html.Raw(Model.Body)
</div>
Note the minwidth/maxwidth lines in the div. Not required, just how I would personally deal with the widths.
Resulting HTML
<div>
<h1>A header!</h1>
</div>
<div class="breakpoint active"
id="bp_1"
data-max-width='720'>
<div>Hello World!</div>
</div>
<div class="breakpoint"
id="bp_2"
data-max-width='720'>
<div>Another Breakpoint</div>
</div>
<div class="breakpoint"
id="bp_3"
data-max-width='720'>
<div>Third Breakpoint</div>
</div>
<div class="breakpoint"
id="bp_4"
data-max-width='720'>
<div>Fourth Breakpoint</div>
</div>
<div>
<h4>A footer!</h4>
</div>
Original Answer
DisplayTemplates are your friend. If your sections are going to be the same, you can put the relevant information into a ViewModel, then pass the List<ViewModel> to the DisplayTemplate. The MVC engine will then use the DisplayTemplate for your ViewModel to fill out the needed code for each section.
You only need code your DisplayTemplate for your ViewModel once.
I don't have any sample code up at the moment, but if you need further help, comment on this and I'll break some out over the weekend.
I'm vague about I should be using in a sort of a simulation app where the user is presented with a web page that presents data from multiple domains and provides a variety of interactions that touch multiple domains.
In this case it is a real estate simulation where the UI presentation shows the user data about houses, offer to buy and sell, status of the users negotiations, etc, information about "state of the world" and that kind of thing. A fair amount of ajax going on in the page as well.
Can I just have a controller which is not associated with a particular domain and then just provide all the different objects? Maybe use a command object to deal with actions coming back from the user?
Hopefully this quesiton is not too vague for a coherent answer, I'm just looking for suggestions on the high level approach.
Yes, you can have a controller which does not directly correlate to a specific domain. For instance you could create a DashboardController. The use of command objects is up to you and your needs, but you can use Domain instance in the above controller just like any other controller.
As #Joshua Moore stated, it's no problem, let me give a small - shortened - example. (hope it gives you a bit of an idea...)
I use in the application a bootstrap-theme and the information on the dashboard (several statistic widgets) is generated through ajax-calls into the dashboard-controller.
First, the UrlMappings.groovy file:
class UrlMappings {
static mappings = {
"/$controller/$action?/$id?(.$format)?"{
constraints {
// apply constraints here
}
}
"/"(controller: "dashboard", action:"index")
"500"(view:'/error')
}
}
Then the controller-code:
package example
import java.util.Random
import grails.converters.JSON
import groovy.time.TimeCategory
class DashboardController {
def index() {}
def contractAmountAsJson() { ...someCode; return Data as JSON... }
}
Then the index.gsp page:
<!DOCTYPE html>
<html>
<head>
<meta name="layout" content="main">
<g:set var="entityName" value="${message(code: 'syParameter.label', default: 'SyParameter')}" />
<title><g:message code="default.list.label" args="[entityName]" /></title>
</head>
<body>
<!-- NEW WIDGET START -->
<article class="col-xs-12 col-sm-6 col-md-6 col-lg-6">
<!-- Widget ID (each widget will need unique ID)-->
<div class="jarviswidget" id="wid-id-8" data-widget-editbutton="false">
<header>
<span class="widget-icon"> <i class="fa fa-bar-chart-o"></i> </span>
<h2>Vertragsvolumen aktiver Kunden-Verträge pro Monat</h2>
</header>
<!-- widget div-->
<div>
<!-- widget edit box -->
<div class="jarviswidget-editbox">
<!-- This area used as dropdown edit box -->
</div>
<!-- end widget edit box -->
<!-- widget content -->
<div class="widget-body no-padding">
<div id="customerContractAmount" class="chart no-padding"></div>
</div>
<!-- end widget content -->
</div>
<!-- end widget div -->
</div>
<!-- end widget -->
</article>
</body>
</html>
And the javascript as an example:
if ($('#customerContractAmount').length) {
$.ajax({
url: '${request.contextPath}/dashboard/contractAmountAsJson?type=customer',
dataType: 'json',
success: function(chartData) {
Morris.${session?.user?.statisticStyle ? session.user.statisticStyle : "Area"}({
element : 'customerContractAmount',
data : chartData,
xkey : 'period',
ykeys : ['a', 'b', 'c'],
labels : ['bestätigt', 'erstellt', 'in Arbeit']
});
}
});
}
I have a list :
$scope.list = ["test/test1/test2/test3","test3/test5/test6"];
I would like to apply bold style to / characters when displaying the list :
<div ng-repeat="path in list">
<p style="font-weight:bold">{{path}}</p>
</div>
Do you have any ideas how can I achieve this ?
Fiddle
you can do it simply with str.replace http://jsfiddle.net/k18vgtvw/
<p style="font-weight:bold" ng-bind-html-unsafe="csc(path)"></p>
controller
$scope.csc = function(path) {
return path.replace(/\//g, "<span style='color:red'>/</span>");
}
There are a number of ways to do this. First I'd add a function to your controller, let's say it's called boldSlashes.
function boldSlashes(path) {
return path.replace("/","<b>/</b>")
}
Then change your html to be:
<div ng-repeat="path in list" ng-bind-html>
boldSlashes({{path}})
</div>
The ng-bind-html tells angular to treat the contents as html and not escape it.
You also have to inject ngSanitize into you module in order to use ng-bind-html.
So wherever you create your module, add ngSanitize to the dependencies like:
angular.module('myApp',[ngSanitize])
I'm not sure if this is what you are trying to do but I separated out individual elements. Also the jsfiddle font the bold font looks exactly the same on the / character.
http://jsfiddle.net/3a2duqg4/
1. Updated the view to a list
2. Changed the array to have an individual item per section
3. Added styles to the "/" and realized the font bold property with the fiddle default font didn't look any different.
<div ng-controller="MyCtrl">
<ul>
<li class="list" ng-repeat="path in list">{{path}} <span>/</span></li>
</ul>
</div>
Added the items to a list rather than a paragraph and added some styles. I updated your array to have one value per array item as well.
Let me know if this helps! :)
var myApp = angular.module('myApp',[]);
function MyCtrl($scope) {
$scope.list = ["test/test1/test2/test3","test3/test5/test6"];
$scope.updateString = function(s) {
return s.replace(/\//g, '<span class="bold">/</span>');
};
}
.bold {
font-weight: bold;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.1/angular.min.js"></script>
<div ng-app="myApp">
<div ng-controller="MyCtrl">
<div ng-repeat="path in list">
<p ng-bind-html-unsafe="updateString(path)"></p>
</div>
</div>
</div>
I want to know what is the current url of my template. I have read here that the "request" is an implicit object present in all templates which returns the url of my template.
So I have tried this:
Controllers:
public class Application extends Controller {
public static Result index() {
return redirect("/home");
}
public static Result home() {
return ok(homePage.render());
}
public static Result aboutUs() {
return ok(aboutUs.render());
}
}
HTML:
leftbar.scala.html file:
<aside id="left-panel">
<nav>
<ul class="animated fadeInLeft">
<li class="#if(request.uri.contains("/aboutus")){active}">(some code here)</li>
</ul>
</nav>
</aside>
homePage.scala.html file:
#scripts = { (some scripts here) }
#views.html.main("Beta Project", scripts) {
#views.html.leftbar()
<div id="main" role="main">
<div id="content">
<span><i class="fa fa-bell"></i>SOMETHING</span>
</div>
</div>
}
Where I import the leftbar.scala.html file I get this error:
not found: value request
What should I do to solve this error? Thanks in advance
A bit more code from your template would be useful, but you can probably fix it by adding
(implicit request: Request[AnyContent])
at the end of the first line on your template.
I am trying to use angular directives to dynamically replace an html portion of a portlet of a page.
The html portlet has 2 sections embedded. The top part has the heading which is obtained from a different backend service
<div class="headerdiv">
<h3 class='headerclass'> Object Heading </h3>
</div>
The content is loaded in to a different section
<div id="objectDiv" ng-controller="ObjectCtrl">
<div ng-show="object.title" mydirective><b>{{object.title}} </b></div>
<div element-trigger><b>{{object.name}} </b></div>
<div element-trigger><b>{{object.description}} </b></div>
</div>
The controller loads the details successfully
The new directive added is
app.directive('mydirective', function(){
return function(scope, elem, attrs){
//obtain old header
var oldHeader = angular.element( '.headerdiv .headerclass' );
//get the new header
//replace old header with new header
}
});
I need to dynamically change the heading in headerdiv with the object.title value . Note that the new directive is bound to the filed that is listening to the object.title div.
I dont think this is the right use of directive, as the directive should be used to affect the functionality of element on which it is defined in most of the cases.
What you can try to do is in ObjectCtrl define a watch on title property, and then broadcast the message
$scope.$watch('object.title',function(newValue) {
$rootScope.$broadcast('titleChanged',newValue); //You can pass any object too
});
If you header is contained inside a controller catch the event
$scope.$on('titleChanged',function(args) {
//Code to handle the title update
});
The html for header should have binding expression for title
<div class="headerdiv">
<h3 class='headerclass'> {{title}} </h3>
</div>
Note: I am not sure about the structure of the html but this all would not be required if the header and the content inside the ObjectCtrl are using the same\shared model (object).