I want to have a UsersAdmin view that has Account Registration, UserProfile class and a Identity Role class. I am using MVC5 with default Individual Authentication.
I am using ui-router for my routing. I have seen many examples using a viewmodel to pass multiple models to a single cshtml view. But I am needing a more complex setup. I created a mock up of what I am looking for. What is the best way to do this.
Here is what my setup looks like
ui-routing
// Default route
$urlRouterProvider.otherwise('/Document');
// Application Routes States
$stateProvider
.state('app', {
abstract: true,
controller: "CoreController",
resolve: {
_assets: Route.require('icons', 'toaster', 'animate')
}
})
.state('app.document', {
url: '/Document',
templateUrl: Route.base('Document/Index'),
resolve: {}
})
.state('app.register', {
url: '/Register',
templateUrl: Route.base('Account/Register'),
resolve: {}
}).state('app.applicationUser', {
url: '/ApplicationUser',
templateUrl: Route.base('ApplicationUsers/Index'),
resolve: {}
}).state('app.role', {
url: '/Role',
templateUrl: Route.base('Role/Index'),
resolve: {}
}).state('app.roleCreate', {
url: '/RoleCreate',
templateUrl: Route.base('Role/Create'),
resolve: {}
}).state('app.userProfile', {
url: '/UserProfile',
templateUrl: Route.base('UserProfiles/Index'),
resolve: {}
}).state('app.userProfileCreate', {
url: '/UserProfileCreate',
templateUrl: Route.base('UserProfiles/Create'),
resolve: {}
}).state('app.login', {
url: '/Login',
templateUrl: Route.base('Account/Login'),
resolve: {}
});
}
_Layout.cshtml
<div ui-view class="app-container" ng-controller="CoreController">#RenderBody()</div>
Navigation
<li>
<a ui-sref="app.userProfile" title="Layouts" ripple="">
<em class="sidebar-item-icon icon-pie-graph"></em>
<span>User Profile</span>
</a>
</li>
I have no issue using modals for the Create,Details,Edit views if that is a easier solution. However I do not know how to pass the selected Id with its properties to the modal.
I believe that I answered your question to someone else. You want to gather information through the URL, right?
Using routes in AngularJS to gather data
ui-router can help you achieve this by using
a.
ui-sref='stateName({param: value, param: value})'
The parameterr object passed along with the state name can be accessed in the controller using $stateParams
b.
In your controller you could do something like
if ($stateParams.id != null) {
// service call goes here
}
c. You need to use named views
Something like
$stateProvider
.state('report', {
views: {
'filters': { ... templates and/or controllers ... },
'tabledata': {},
'graph': {},
}
})
where
filters
and
tabledate
are the named views.
ui-view has a decent example for it here https://github.com/angular-ui/ui-router/wiki/Multiple-Named-Views
Btw , I would suggest you first figure out the panels which are dynamic ( i.e the ones whose content changes because of some kind of user interaction ) vs static ones ( they dont change once loaded) . You should only be looking at ui-views to replace the dynamic parts , there is no point in making the app more complicated by putting everything in a child view . The states can become very confusing very quickly.
I use the ng-include directive to load the static views in the parent state and only define child states for portion of the views that change.
<div ng-include="'/MyStaticView'" ng-show="MyCondition == true "></div>
Related
How can I escape client side routing when wanting to navigate outside the set list of routes setup in the router?
I created a project using Durandal.js and have created SPA's inside different Areas. The problem I ran into is that when I want to navigate outside the current SPA and into another or say back to the home page of the entire application which is not an SPA at all but simply a cshtml page.
What I have tried to do is use Durandal's mapUnknownRoutes handler to intercept and then use window.location.href to navigate out. This works, but when I want to go the home page of the application ("/"), the router matches the "root" of the SPA and doesn't navigate out to the home page but instead the SPA's root route.
The area route in this example is "/spaHome" whose MVC route looks like:
context.MapRoute(
"spaHome_default",
"spaHome/{*catchall}",
new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
Here's what I've done to set up the Durandal router:
var routes = [
{ route: ['spaHome', ''], moduleId: 'spaHome', title: "spaHome", hash: "#spaHome"},
{ route: 'one/anotherPage', moduleId: 'one/anotherPage', title: "one/anotherPage", hash: "#one/anotherPage"}
];
router.makeRelative({ moduleId: 'viewmodels' });
router.map(routes)
.mapUnknownRoutes(function (instruction) {
utils.navigateToPath(instruction.fragment);
return false;
})
.activate({ pushState: true, root: "/spaHome" });
Any pointers or leads into the right direction for this would be much appreciated!
After some trial and error I was able to come up with a solution to what I was trying accomplish. It looks like a solid solution, so hopefully it doesn't cause any issues down the road.
I changed the routes array and removed the default route of '' from the first route. This allowed me to have a unknown route to go off of when wanting to hit the normal MVC homepage. I also had to remove the "root" property from the activate function of the router. Which in turn meant I had to explicitly declare the routes in the route array with the extra area portion or the URL ("spaHome/").
Then in my mapUnknownRoutes handler I checked the route for the area portion of the URL, and if that existed, I used the SPA router to show a notfound page for that SPA. Else I assumed that the route exists outside the area and I need to hard navigate to the URL using window.location.href.
var routes = [
{ route: ['spaHome'], moduleId: 'spaHome', title: "spaHome", hash: "#spaHome"},
{ route: 'spaHome/one/anotherPage', moduleId: 'one/anotherPage', title: "one/anotherPage", hash: "#spaHome/one/anotherPage"}
];
router.makeRelative({ moduleId: 'viewmodels' });
router.map(routes)
.mapUnknownRoutes(function (instruction) {
if (instruction.fragment.toLowerCase().indexOf("spaHome/", 0) === -1) {
utils.navigateToPath(instruction.fragment);
} else {
var notfoundRoute = "notfound";
instruction.config.moduleId = notfoundRoute;
history.navigate(notfoundRoute, { trigger: false, replace: true });
}
})
.activate({ pushState: true });
If anyone has a better solution please let me know!
EDIT
Ok, I ran into an issue with the history while doing this. I had to add a line to the Durandal router.js file to stop the previous route from being added to the history queue.
if (!instruction.cancelQueue) {
router.trigger('router:route:before-config', instruction.config, router);
router.trigger('router:route:after-config', instruction.config, router);
queueInstruction(instruction);
}
Edit 2
I also ran into an issue with this method where the navigation doesn't work quite right for IE9 and below.
I'm trying to build a SPA with Asp.Net MVC. for this I'm using angularJs routing .
This is my project hierarchy.
My Layout.cshtl code
<html lang="en" ng-app="ProjectTrackingModule">
<head>
<script src="~/Scripts/jquery-2.1.0.min.js"></script>
<script src="~/Scripts/angular.min.js"></script>
<script src="~/Scripts/angular-route.min.js"></script>
<script src="~/Scripts/app.js"></script>
</head>
<body>
Home
Projects
<div ng‐view style="margin‐left: 10%; margin‐right: 10%;">
</div>
//... footer
</body>
</html>
My app.Js code is as follow:
var app = angular.module('ProjectTrackingModule', ['ngRoute', 'ui.bootstrap']);
app.config(function ($routeProvider) {
$routeProvider
.when("/Home", {
templateUrl: "/Views/Home/Home.cshtml",
controller:"HomeController"
})
.when("/Projects", {
templateUrl: "/Views/ProjectManagement/ProjectDetails.cshtml",
controller: "ProjectsController"
})
.otherwise({redirectTo:"/Home"})
});
I want to load my Home.Cshtml partial view inside ng-view. But when I run my application, It only showing Home partial view.
also when I click on Project, then it should render ProjectDetails.cshtml inside ng-view.
code inside ProjectDetails.cshtml
<div ng-controller="ProjectsController">
<h2>ProjectDetails</h2>
</div>
I think you have some misonceptions about Angularjs routing concepts.
MVC Routing :
ASP.NET routing enables you to use URLs that do not have to map to specific files in a Web site. Because the URL does not have to map to a file, you can use URLs that are descriptive of the user's action and therefore are more easily understood by users.
Angular Routing :
Angular.js routing using MVC framework does not use MVC routing.
Comparable parts are:
Model ===== ng-module
controller ===== ng-controller
view ===== ng-view
So you can't call the MVC Controller in your angularjs route config. Does this make sense?
Also please think about some of the differences between cshtml and html.
Angular routing and MVC routing are totally different because:
Angular routing is use client side
MVC routing is used server side
The above texts are for your understanding only.
I think this discussion will help you :
How to use ASP.NET MVC and AngularJS routing?
Update :
The href is wrong in Anchor tag.
Its should be href="#/Home", not href="#Home"
So please change your code
Home
Projects
Lets understand the routing in angular first. lets say your url says
www.example.com/Home/Index -- this points to your MVC HomeController and Index ActionMethod. Now what mvc does, it returns you the first View only.
say you have an anchor Load the New View. Clicking this will result in a new Url www.example.com/Home/Index#/angular-route. This url will still hit the same MVC HomeController and ActionMethod.
But you have an additional route in angular
`var app = angular.module('ProjectTrackingModule', ['ngRoute', 'ui.bootstrap']);
app.config(function ($routeProvider) {
$routeProvider
.when("/angular-route", {
templateUrl: "/Html/GetHtml?type=angular-route",
controller:"AngularController"
})
.otherwise({redirectTo:"/Home"})
});`
Here in the code section templateUrl: "/Html/GetHtml?type=angular-route",
Html is MVC Controller and GetHtml is ActionMethod. This ActionMethod returns you the new view that you want according to the angular route, that's why we are sending a parameter type too to help us decide.
controller:"AngularController" says that angular will call its controller after the page is returned from you mvc controller. It's Angular's Controller and it has nothing to do with your MVC controller.
you declare angular controller like this:
app.controller('AngularController',function($scope){
alert("my js controller is called");
});
Hope this helps you to find a solution.
Have a simple example can apply to your project. Example our MVC application has four pages as Home, Contact, About and User, we want to create a angularjs template for each pages, so how we do routing for it? how to make angularjs controller for it?
Basic code as following:
Routing:
$routeProvider
.when('/', { // For Home Page
templateUrl: '/AngularTemplates/Home.html',
controller: 'HomeController'
})
.when('/Home/Contact', { // For Contact page
templateUrl: '/AngularTemplates/Contact.html',
controller: 'ContactController'
})
.when('/Home/About', { // For About page
templateUrl: '/AngularTemplates/About.html',
controller: 'AboutController'
})
.when('/Home/User/:userid', { // For User page with userid parameter
templateUrl: '/AngularTemplates/User.html',
controller: 'UserController'
})
.otherwise({ // This is when any route not matched => error
controller: 'ErrorController'
})
}]);
Controller:
var app = angular.module('MyApp'); app.controller('UserController', ['$scope', '$routeParams', function ($scope, $routeParams) {
$scope.Message = "This is User Page with query string id value = " + $routeParams.userid;}]); ...
Full article with download code for it at Angularjs routing asp.net mvc example
You cannot directly point on the .cshtml file but you can point to a templateUrl that points to an MVC route.
Considering you are using the default MVC route {controller}/{action}/{id?}, for example:
var app = angular.module('ProjectTrackingModule', ['ngRoute', 'ui.bootstrap']);
app.config(function ($routeProvider) {
$routeProvider
.when("/Home", {
templateUrl: "/Home/Home", //points to an mvc route controller=Home, action=Home
controller:"HomeController"
})
.otherwise({redirectTo:"/Home"})
});
But in order for it to work the MVC Action should be in the controller also.
public class HomeController : Controller
{
[HttpGet]
public ActionResult Home()
{
return View();
}
}
also your anchor tags points to an incorrect href, it should have the hashbang (#)
Home
Projects
Simple way to do it would be like follows:
MyAngularApp.js
var myAngularApp = angular.module('MyAngularApp', ['ngRoute']);
myAngularApp.config(function ($routeProvider) {
$routeProvider
.when("/myprojects", {
templateUrl: "MyAspMvcCtrl/GetTemplate?id=myprojects",
controller:"MyAngularController"
})
...
.otherwise({redirectTo:"/myprojects"})
});
myAngularApp.controller("MyAngularController", function ($scope) {
...
// Do something
$scope.mydata = {
id = 1234,
msg = "Hello"
};
});
ASP.Net MVC Controller
public class MyAspMvcCtrlController : Controller
{
[HttpGet]
public ActionResult GetTemplate(string id)
{
switch (id.ToLower())
{
case "myprojects":
return PartialView("~/Views/ProjectManagement/ProjectDetails.cshtml");
default:
throw new Exception("Unknown template request");
}
}
}
Layout.cshtml
<html ng-app="myAngularApp">
...
<body>
...
<div ...>
...
My Projects
...
</div>
<div ng-view></div>
...
</body>
</html>
ProjectDetails.cshtml
<div ...>
<h3>ID: {{mydata.id}}</h3>
<p>Message: {{mydata.msg}}</p>
</div>
AngularJs Routing Does not working with cshtml files !!
if you want to use angularjs routing with mvc view (cshtml) file use both routing:
angular routing + mvc routing
your routing code should be like this:
.when("/Home", {
templateUrl: "/Home/Home",
controller:"HomeController"
});
where First Home is Controller Name
and Second Home is The Action Name at the Mvc Controller.
I have a MVC View (Say Index) where I am loading multiple views via AngularJS and I have defined the angular route something like
angular.module("myModule", []).config(function ($routeProvider, $locationProvider) {
$routeProvider.when('/Home/View1', { templateUrl: '/ngViews/View1.html', controller: 'Controller1' });
$routeProvider.when('/Home/View2', { templateUrl: '/ngviews/View2.html', controller: 'Controller2' });
$locationProvider.html5Mode(true); });
Now I want if there is link like /Home/Details (or Test/AnotherAction )which is not provided using $routeprovider then it should call MVC action. Please suggest the best way to handle it.
Thanks a lot in advance
I'm currently working on an ASP.NET MVC project to which some AngularJS was added - including some AngularJS directives.
I need to add to an AngularJS directive a MVC partial view. Obviously,
#Html.Partial("_PartialView", {{name}})
doesn't work.
So far all my searches online provided no help.
Any idea how I could render a partial view inside an Angular directive?
Thanks!
Angular exists strictly on the client side whereas MVC views exist on the server side. These two cannot interact directly. However, you could create an endpoint in which your partial view is returned as HTML. Angular could call this endpoint, retrieve the HTML, and then include it inside a directive.
Something like this:
app.directive("specialView", function($http) {
return {
link: function(scope, element) {
$http.get("/views/partials/special-view") // immediately call to retrieve partial
.success(function(data) {
element.html(data); // replace insides of this element with response
});
}
};
});
app.directive("myDirective", ['', function () {
return {
restrict: 'A',
scope: {
foo: '='
},
templateUrl: '/home/_myDirectivePartialView',
}]
} }]);
Just need to use templareURL and specify the route to get the partial view.
I'm developing a webapp using AngularJS and Laravel.
When I navigate through URL and links in the app everything works fine, but if I type an URL directly in the browser, something strange happens.
For example, If I type http://myapp.dev/#/customers I get redirected to http://myapp.dev/customers#/
Why? What's wrong? Laravel executes "/" route (right) and Angular "/" route (right, again).
Note: I have made a test application similar to the first but without using Laravel and .htaccess (it serves only static HTML) and I haven't this issue, I can access URL directly.
Thank you.
Edit - here the Angular routing code:
var App = angular.module('Factotum', ['ngResource']);
function appRouteConfig($routeProvider) {
$routeProvider.
when('/', {
controller: IndiceController,
templateUrl: 'v/indice'
}).
when('/login', {
controller: 'AppController',
templateUrl: 'v/login'
}).
when('/logout', {
controller: 'AppController',
templateUrl: 'v/login'
}).
// ---- Clienti
when('/clienti', {
controller: ClientiController,
templateUrl: 'v/clienti/lista'
}).
when('/clienti/nuovo', {
controller: ClientiController,
templateUrl: 'v/clienti/nuovo'
}).
when('/clienti/modifica/:id', {
controller: ClientiController,
templateUrl: 'v/clienti/modifica'
}).
// ---- Progetti
when('/progetti', {
controller: ProgettiController,
templateUrl: 'v/progetti/lista'
}).
when('/progetti/nuovo', {
controller: ProgettiController,
templateUrl: 'v/progetti/nuovo'
}).
otherwise({
redirectTo: '/'
});
} // factotumRouteConfig
App.config(appRouteConfig);
Finally I found the problem. I'm using a free HTML5 template (Charisma by Usman - here a demo: http://usman.it/themes/charisma/), which includes jQuery History plugin. I removed this plugin, along with some initialization code, and now all is working as expected.
My fault, I didn't inspect the code carefully.