Can't get child views to load in AngularJS with ui-router - asp.net-mvc

I'm trying to understand the concept of using the ui-router (v0.2.10) with AngularJS (v1.2.15) through converting an old project that previously used ngRoute and have been unable to figure out why it isn't working. I have an ASP.NET MVC website that shows the base page with something similar to the following:
index.cshtml
<!DOCTYPE html>
<html lang="en-US" ng-app="home">
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
#Styles.Render("~/Content/css")
</head>
<body>
<div ui-view></div>
#Scripts.Render(*all the angular, jquery and other script references here)
</body>
</html>
app.js
angular.module('home') ['ui.router'])
.config(function ($stateProvider, $urlRouterProvider, $locationProvider) {
$urlRouterProvider.when("", "/");
$urlRouterProvider.otherwise("/");
var root = {
name: 'root',
url: '/',
abstract: true,
templateUrl: '/Scripts/home/templates/root.html',
controller: 'RootController'
};
var home = {
name: 'root.home',
url: '/home',
parent: root,
templateUrl: 'Scripts/home/templates/home.html',
controller: 'HomeController'
};
$stateProvider
.state(root)
.state(home);
$locationProvider.html5Mode(true);
};
rootCtrl.js
angular.module('home').controller('RootController', function() {
});
homeCtrl.js
angular.module('home').controller('HomeController', function() {
});
root.html
<navbar/>
<div class="wrapper" style="padding-top:25px;margin-bottom:20px">
<div ui-view></div>
</div>
<footer/>
navbar.js
angular.module('home').directive('navbar', function() {
return {
restrict: 'E',
replace: true,
templateUrl: '/Scripts/home/templates/directives/navbar.html'
};
});
The navbar directive template simply contains the bootstrap navbar.
footer.js
angular.module('home').directive('footer', function() {
return {
restrict: 'E',
replace: true,
templateUrl: '/Scripts/home/templates/directives/footer.html'
};
});
Except that nothing shows up on the page except for the CSS references at the top, the following, and then the javascript references at the bottom:
Why doesn't the root.html view show up on the screen when I load up the page? Thanks!

As per another answer on this site, one cannot self-close the tags for custom directives. Thus, if I change the tags in root.html to the following:
<navbar></navbar>
<div class="wrapper" style="padding-top:25px;margin-bottom:20px">
<div ui-view></div>
</div>
<footer></footer>
It works fine.

Related

How to hide text-boxes in Asp.net

I'm creating a leave system and I've linked the database with Asp.net. Inside the mvc project there's an HTML page that I use as my landing page, it has 2 buttons. One button for 'Admin' and other for 'Staff'. I want to hide some of the text-boxes if the 'Staff' button is clicked. How do I go about achieving this?
I have created sample html, you can use jquery to show and hide your textbox based on click
if you are using mvc then your textbox is #Html.TextBox or
with asp.net set ClientIDMode="Static" - check here
<html>
<head>
<script src="https://code.jquery.com/jquery-1.10.2.js"></script>
</head>
<body>
<input type="text" id="AdminTxt" />
<button id="showAdmin">Show Admin</button>
<button id="showStaff">Show Staff</button>
<script>
$( "#showAdmin" ).click(function() {
$("#AdminTxt").show();
});
$( "#showStaff" ).click(function() {
$("#AdminTxt").hide();
});
</script>
</body>
</html>
You can use the attach en detach functions with JQuery.
So if you have a button called Admin
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>detach demo</title>
<style>
p {
background: yellow;
margin: 6px 0;
}
p.off {
background: black;
}
</style>
<script src="https://code.jquery.com/jquery-1.10.2.js"></script>
</head>
<body>
<p>Hello</p>
how are
<p>you?</p>
<button>Attach/detach paragraphs</button>
<script>
$( "p" ).click(function() {
$( this ).toggleClass( "off" );
});
var p;
$( "button" ).click(function() {
if ( p ) {
p.appendTo( "body" );
p = null;
} else {
p = $( "p" ).detach();
}
});
</script>
</body>
</html>

View not loading in angular js app

This is my index.cshtml (view to which I re-direct from the server side controller)
<!DOCTYPE html>
<html lang="en" ng-app="AlumnusApp" class="no-js">
<head>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.12/angular.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.12/angular-route.js"></script>
<script src="~/Scripts/AlumnusScripts/AlumnusApp.js"></script>
<script src="~/Scripts/AlumnusScripts/AlumnusController.js"></script>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>My AngularJS App</title>
</head>
<body>
<div></div>
<div ng-view></div>
</body>
</html>
My app and controller are as below
'use strict';
// Declare app level module which depends on filters, and services
angular.module('AlumnusApp',['ngRoute']).
config(['$routeProvider', function ($routeProvider) {
debugger;
$routeProvider.when('/Home', { templateUrl: '/Views/Home/Home.html', controller: 'HomeCtrl' });
$routeProvider.otherwise({ redirectTo: '/Home' });
}]);
/* Controllers */
angular.module('AlumnusApp')
.controller('HomeCtrl', ['$scope', function ($scope) {
alert('1');
}])
However when I try to load the Home view it gives following error:-
http://localhost:2614/Views/Home/Home.html 404 (Not Found)
The path of the view is correct. Any suggestions?
try below templateUrl's
templateUrl: 'Views/Home/Home.html'
OR
templateUrl: '/Views/Home/Home.html'
OR
templateUrl: '../Views/Home/Home.html'

angular directive compile order

I was trying to write a simple directive to generate a (potentially) more complex dom element. I am quite confused about what is going on here but I think the directive I use inside my directive get linked first? Anyway the element I am generating is not visible where it should.
Sorry for all that confusion, here is the plunkr:
http://plnkr.co/edit/vWxTmA1tQ2rz6Z9dJyU9?p=preview
I think the directive I use inside my directive get linked first?
Yes. A child directive's link function will execute before the parent's link function.
Here is a fiddle that shows two nested directives,
<div d1>
<div d2></div>
</div>
and it logs when the directives' controller and link functions are called.
There are a few issues with your Plunker:
Since you are using # for your isolate scopes, you need to use {{}}s in your attribute values:
<visible value='{{visible}}'>plop</visible>
<invisible value='{{visible}}'>plop</invisible>
Since $scope.visible is defined in your controller, I assume you meant to use that value, and not test.
In the invisible directive, you need to use isolate scope property value in your link function. Property visible is available to the transcluded scope (which is in affect if you use a template in your directive like #Langdon has) but not the isolate scope, which is what the link function sees.
var template = "<span ng-show='value'>{{value}}</span>";
Plunker.
If you want a simple directive, you're better off letting Angular do most of the work through ngTransclude, and $watch.
http://plnkr.co/edit/xYTNIUKYuHWhTrK80qKJ?p=preview
HTML:
<!doctype html>
<html ng-app="app">
<head>
<meta charset="utf-8">
<title>trying to compile stuff</title>
<script src="http://code.angularjs.org/1.1.1/angular.js"></script>
<script src="app.js"></script>
</head>
<body>
<div ng-controller="AppCtrl">
<input type="checkbox" ng-model="test" id="test" /><label for="test">Visibility (currently {{test}})</label>
<br />
<br />
<visible value='test'>visible tag</visible>
<invisible value='test'>invisible tag</invisible>
</div>
</body>
</html>
JavaScript:
angular
.module('app', [])
.controller('AppCtrl', function($scope) {
$scope.test = false;
})
.directive('visible', function() {
return {
restrict: 'E',
transclude: true,
template: '<span ng-transclude></span>',
replace: true,
scope: {
value: '='
},
link: function(scope, element, attrs) {
console.log(attrs);
scope.$watch('value', function (value) {
element.css('display', value ? '' : 'none');
});
console.log(attrs.value);
}
};
})
.directive('invisible', function() {
return {
restrict: 'E',
transclude: true,
template: '<span ng-transclude></span>',
replace: true,
scope: {
value: '='
},
link: function(scope, element, attrs) {
scope.$watch('value', function (value) {
element.css('display', value ? 'none' : '');
});
}
};
});

How can I have an AngularJS module routes use its own controllers?

I'm trying to learn AngularJS' view and routing mechanism, following AngularJS' own tutorial.
My problem is the tutorial is declaring all its controllers in the global scope, and I belive this is a bad practice because we're polluting it as we add more controllers.
This is a quick working page I've been able to build following the aforementioned tutorial (there's a fiddle, too):
<!doctype html>
<html>
<head>
<title>Test</title>
<script src="http://cdnjs.cloudflare.com/ajax/libs/jquery/1.9.1/jquery.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/angular.js/1.1.1/angular.js"></script>
<script>
"use strict";
var MyFirstController = function ($scope) {
// Do something here.
};
var MySecondController = function ($scope) {
// Do something here.
};
var myModule = angular.module("MyModule", []);
myModule.config(["$routeProvider", function ($routeProvider) {
$routeProvider.when("/first-page", {
template: "<p>My first controller.</p>",
controller: MyFirstController
});
$routeProvider.when("/second-page", {
template: "<p>My second controller.</p>",
controller: MySecondController
});
}]);
$(document).ready(function () {
angular.bootstrap(document, ["MyModule"]);
});
</script>
</head>
<body>
<h1>Test</h1>
<div data-ng-view></div>
<p>Click me!</p>
<p>Click me too!</p>
</body>
</html>
Being naïve, I tried to move the controllers inside the module:
myModule.config(["$routeProvider", function ($routeProvider) {
$routeProvider.when("/first-page", {
template: "<p>My first controller.</p>",
controller: MyFirstController
});
$routeProvider.when("/second-page", {
template: "<p>My second controller.</p>",
controller: MySecondController
});
}]);
myModule.controller("MyFirstController", ["$scope", function ($scope) {
// Do something here.
}]);
myModule.controller("MySecondController", ["$scope", function ($scope) {
// Do something here.
}]);
Alas, it doesn't (obviously) work, throwing a ReferenceError: MyFirstController is not defined exception.
How can I have an AngularJS module use its own controllers in its own routes configuration?
Once you know the solution, it's really simple: just specify the controller as strings instead of objects:
myModule.config(["$routeProvider", function ($routeProvider) {
$routeProvider.when("/first-page", {
template: "<p>My first controller.</p>",
controller: "MyFirstController"
});
$routeProvider.when("/second-page", {
template: "<p>My second controller.</p>",
controller: "MySecondController"
});
}]);
This way AngularJS will resolve the controller name to the one you've defined inside the module.
And it's minification safe too!
I've created a fiddle demonstrating it.

jquery-ui .tabs ajax load specific content of page?

I'm trying to use jQuery UI's .tabs() to obtain content via AJAX, but the default behavior is to grab the entire page's content. How would I obtain content from a specific #id and/or multiple #id's?
I have a feeling I will need to use the load: event (http://docs.jquery.com/UI/Tabs#event-load), but I need an assist figuring this out.
Example:
The Page with the tabs that is getting and displaying the tabbed content. I have placed #content after the first #the_tabs link to retrieve in an attempt to obtain that specific region of the content, but the entire page is still loaded.
<div id="tabs">
<div id="tabs_display">
</div>
<ul id="the_tabs">
<li><span>1</span></li>
<li><span>2</span></li>
<li><span>3</span></li>
<li><span>4</span></li>
</ul>
</div><!-- /#tabs -->
The page being retrieved by the previous markup:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<title>Remote HTML Page Example</title>
</head>
<body>
<div id="content">
I want this content
</div>
<div id="other_stuff">
Not this content
</div>
</body>
</html>
the JS (for setup purposes):
$(document).ready(function(){
/* Tabs
--------------------*/
$(function() {
var $tabs = $('#tabs').tabs({
});
});
});
In Jquery-UI 1.9, "ajaxOptions" is depreciated; so instead the code below worked for me:
(ref: http://jqueryui.com/upgrade-guide/1.9/#deprecated-ajaxoptions-and-cache-options-added-beforeload-event)
$(function() {
$( "#the_tabs" ).tabs({
beforeLoad: function( event, ui ) {
ui.ajaxSettings.dataType = 'html';
ui.ajaxSettings.dataFilter = function(data) {
return $(data).filter("#content").html();
};
}
});
});
$(document).ready(function(){
/* Tabs
--------------------*/
var $tabs = $('#the_tabs').tabs({
ajaxOptions: {
dataFilter: function(data, type){
return $(data).filter("#content").html();
}
}
});
});
Solution props to Supavisah in #jquery on irc.freenode.net
I have had luck using .find, rather than .filter. Like this:
$(document).ready(function(){
$('#the_tabs').tabs({
ajaxOptions: {
cache : true,
dataFilter: function(data){
return $(data).find('#content');
},
}
});
});

Resources