Problem with ng-if in ng-include html template from root controller - javascript

I come from Angular9 and am really used to it, and I have been asked to work a bit on an AngularJS project, which I have never experienced. So I am really struggling with the whole app structure.
My issue is simple: I have a sub-navbar.html template directly injected in my root.html template using ng-include, and I would like to condition the display of one section of this sub-navbar with 'ng-if' (not just hide the section, I don't want it there at all).
I have a backend call which sends me a boolean according to whether the connected user can see the section or not.
The problem I have is that my section is actually never active even when the boolean is 'true'.
Things I tried:
Change the priority of the ng-if and 'ng-controller' directives ---> Broke the app
Add a new 'subnavbar-controller' and declare it as a .state in the app.js ---> Didn't work
Create a custom directive ---> Can't figure out hw the work apparently, didn't work
I unfortunately can't copy all my code, but here are the main pieces I'm working on:
app.js: (I wrote nothing concerning this '$rootScope.adminSection' in the '.run()' function and also tried the same approach directly calling the service without the '$onInit')
$urlRouterProvider.otherwise("/orders");
$stateProvider
.state('root', {
abstract: true,
url: '',
views: {
'': {
templateUrl: "view/root.html",
controller: ['$rootScope', 'AdministratorService', function ($rootScope, AdministratorService) {
const vm = this;
vm.$onInit = function() {
AdministratorService.getAdminSection().then(function (result) {
$rootScope.adminSection = result;
}
)
};
}]
}
}])
root.html:
<div ui-view="root_header"></div>
<div class="row" style="min-height: 600px">
<div class="col-md-2">
<br/>
<div ng-include="'view/subnavbar.html'"></div>
</div>
<div class="col-md-10">
<div ui-view></div>
</div>
</div>
<div ng-include="'view/footer.html'"></div>
subnavbar.html:
<ul class="nav nav-pills nav-stacked" role="tablist">
<li></li>
<li ui-sref-active="active"><a ui-sref="root.contracts"></a><div class='arrow' aria-hidden='true'></div>
</li>
<li ng-if="$rootScope.adminSection" ui-sref-active="active"><a ui-sref="root.administrator">
</a><div class='arrow' aria-hidden='true'></div></li>
<li ui-sref-active="active"><a ui-sref="root.users"></a><div class='arrow' aria-hidden='true'>
</div></li>
</ul>
Any help welcome, thanks in advance !

There are several ways this can work. The reason it is not working now is that $rootScope in the template is not defined. Try, in your template, to replace $rootScope.adminSection with just adminSection.
ngInclude directive creates a new scope which inherits from $rootScope. Therefore, variables in $rootScope should be directly accessible from the template.

Related

How to keep my Navbar on top of every HTML page (avoiding copying the same code)

this is quite simple i think, i have a navbar with my tabs that need to be displayed on all my html pages, i have a .html page for each tab. How can i make it so that i dont have to copy the navbar code into every html page (trying to avoid copying the code since this is messy and a lot of work if i gotta change something).
Im trying to avoid PHP in my project, id prefer Java or AngularJS
Heres the relevant part of the index.html
<ul class="nav nav-pills nav-justified">
<li class="active">Home</li>
<li>Maschinen/Tätigkeiten</li>
<li>Personen</li>
</ul>
Angularjs provide you two different solutions for achieving this.
1) Make a directive for you nav-bar
https://docs.angularjs.org/guide/directive
You can place your nav-bar's code into the directive html file, en call your nav-bar everywhere you need id with the directive's balise. Something like this :
<my-nav-bar></my-nav-bar>
2) Using angular ui-rooter
I think that is the better choice here. You will have a main html file with a <ui-view></ui-view>. When you change of page, only the content of the ui-view is changed. So you have to place your nav-bar outside the ui-view.
You have an example of what you can do here :
https://angular-ui.github.io/ui-router/sample/#/about
PS : don't forget to had the angular-ui-rooter js file to your project if you want to try this solution.
Hope this help.
A+
You can use php or another backend language to make a header file and include that in your other pages.
Alternatively, you can use something like Jade and use their includes.
See here: http://jade-lang.com/reference/includes/
I also think using angular-ui-router for this will be the best.
You can create one <div ui-view></div> for your app and then create an abstract state that will load your base template with your header in it. Something like this could be your base template:
<ul><li>...</li>...</ul>
<div ui-view="content"></div>
Then in every child state of base you can add your content to the named view 'content'.
With ui-sref-active="active" it's easy to highlight the currently active link.
Please have a look at the demo below or this fiddle.
angular.module('demoApp', ['ui.router'])
.config(routeConfig);
function routeConfig($urlRouterProvider, $stateProvider) {
$urlRouterProvider.otherwise('/');
$stateProvider.state('base', {
url: '/',
abstract: true,
templateUrl: 'partials/base.html'
})
.state('base.home', {
url: '',
views: {
'content': {
templateUrl: 'pages/home.html',
controller: function() {
console.log('home controller');
}
}
}
})
.state('base.machines', {
url: '/machines',
views: {
'content': {
templateUrl: 'pages/machines.html',
controller: function() {
console.log('machines controller');
}
}
}
})
.state('base.persons', {
url: '/persons',
views: {
'content': {
templateUrl: 'pages/persons.html',
controller: function() {
console.log('persons controller');
}
}
}
})
}
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.3/angular.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-router/0.2.18/angular-ui-router.js"></script>
<div ng-app="demoApp">
<div ui-view></div>
<script type="text/ng-template" id="partials/base.html">
<ul class="nav nav-pills nav-justified">
<li ui-sref-active="active"><a ui-sref="base.home">Home</a></li>
<li ui-sref-active="active"><a ui-sref="base.machines">Maschinen/Tätigkeiten</a></li>
<li ui-sref-active="active"><a ui-sref="base.persons">Personen</a></li>
</ul>
<div ui-view="content"></div>
<!-- here you could add a footer view -->
</script>
<script type="text/ng-template" id="pages/home.html">
home
</script>
<script type="text/ng-template" id="pages/machines.html">
machines
</script>
<script type="text/ng-template" id="pages/persons.html">
persons
</script>
</div>

href not working as expected

I'm using this snippet from HERE. It looks ok, but when I click on a tab, instead of changing the content of the body (<a href="#tab2success" data-toggle="tab">), it redirects to localhost:9000/#tab2success, which does not exist. How is it possible to achieve this? I just want that when clicking on the tab, it goes to the specific content in the body. Looks like that href is not the solution here...
<div class="col-md-9">
<div class="panel with-nav-tabs panel-success">
<div class="panel-heading">
<ul class="nav nav-tabs">
<li class="active">Success 1</li>
<li>Success 2</li>
<li>Success 3</li>
</ul>
</div>
<div class="panel-body">
<div class="tab-content">
<div class="tab-pane fade in active" id="tab1success">Success 1</div>
<div class="tab-pane fade" id="tab2success">Success 2</div>
<div class="tab-pane fade" id="tab3success">Success 3</div>
</div>
</div>
PD: I'm using angularJS, so if there is any directive or something that could help, it may be also a valid option.
EDIT: Part of my router implementation. It's just o part of the code, because it's too longo to post it all..
angular
.module('Test', [ //setting a module
'oc.lazyLoad',
'ui.router',
'ui.bootstrap',
'angular-loading-bar'
])
.config(['$stateProvider', '$urlRouterProvider', '$ocLazyLoadProvider', function ($stateProvider, $urlRouterProvider, $ocLazyLoadProvider) {
$ocLazyLoadProvider.config({
//$ocLazyLoad returns a promise that will be rejected when there is an error but if you set debug to true, //$ocLazyLoad will also log all errors to the console.
debug: false,
events: true,
});
// For any unmatched url, redirect to '/dashboard/home'
$urlRouterProvider.otherwise('/dashboard/rank');
// Now we set up the states
$stateProvider
.state('dashboard', { //parent view
url: '/dashboard',
templateUrl: 'views/dashboard/main.html',
This is the normal behavior for href's.
To solve your issue please refer to this article :
Nav tabs in Angular
Basically, there is a flag that controls the visibility of tabs and a ng-click event that will update the value for the flag.
Once the value of the model (flag) was updated, it will automatically update the view.
This is exactly the expected behaviour of href - if you don't supply a full URL, it'll append it onto your current URL (I'm assuming you are using localhost:9000 while developing). Have a look at this link which explains how to use it right, utilising ng-href directive.
To sum it up, you need to use the "handlebars" format inside the ng-href directive:
<a ng-href="{{/#tab2success}}" data-toggle="tab">
There is no need for any Angular code or overcomplications. You are just missing the bootstrap.js file that operates the tabs.
Make sure you are using the correct classes of the tab markup, import the JS file at the end of the body of your document, and that's it.
You can read more about the Bootstrap tabs, the markup, and the way they work in the official Bootstrap documentation.

AngularJS coupling between view and controller

I have an AngularJS application in which I started off with my view files having the controller defined using the ng-controller directive.
myview.html
<div ng-controller="MyController">
<ul>
<li class="thumb" ng-repeat="item in items">
<span profile ng-click="getItem(item.id)"></span>
</li>
</ul>
</div>
However, I am now using routing and my controller is defined as part of my routeProvider configuration.
myview.html
<div>
<ul>
<li class="thumb" ng-repeat="item in items">
<span profile ng-click="getItem(item.id)"></span>
</li>
</ul>
</div>
router.js
.when('/homepage', {
templateUrl: 'templates/myview.html',
controller: 'MyController'
})
This works, but although at first it seemed like this was helping me to decouple my view from my controller, something feels off as I still have references to scope member variables in my view and these are tied to my controller.
Am I missing something here? What have I gained from specifying MyController in my routeProvider and not in my template?
For all practical purposes I don't believe you gained anything, except from conforming to the standard way of defining routes, views and controllers in AngularJS.
If we're thinking programming principles and MVC, your view now doesn't know anything about the controller, it is only dependent on the model (that'd be $scope in angular), which is fine and perfectly normal in a MVC-architecture.
By defining the controller in your route, you can use the same view (template) in multiple controller (and pass different scoped data)
For example:
.when('/homepage', {
templateUrl: 'templates/myview.html',
controller: 'MyController'
})
.when('/list', {
templateUrl: 'templates/myview.html',
controller: 'MyListController'
})

How to insert HTML by id using something like AngularJS ng-include

I'm using AngularJS and compiling a directive into my main page. The directive has a set of buttons that change depending on what is happening in the directive.
I would like to move the buttons to something like a menu-bar in my page, but the menu-bar is not part of the directive.
Would it be possible to use something like ng-include to insert the buttons in the menu-bar?
An example of what I would like to do:
<body ng-app="myApp" ng-controller="Controller">
<nav class="navbar">
<ul class="nav nav-pills">
<li>
<button>A permanent button</button>
</li>
<div ng-include="#other-buttons></div>
</ul>
</nav>
<my-directive></my-directive>
<script type="text/javascript">
angular.module('myApp', [])
.controller('Controller', ['$scope', function($scope) {
$scope.data = someData;
}])
.directive('myDirective', function() {
return {
template: '<div id="other-buttons" ng-switch="data">
<div ng-switch-when="this">
<li><button>This button</a></li>
</div>
<div data-ng-switch-when="that">
<li><button>That button</a></li>
</div>
</div>'
};
});
</script
</body
So depending on some data the directive template will be different, which should change the content in the nav-bar. How would doing that work?
You can use $templateCache to set and get templates, and then reference them by the ids you gave them. You can see the examples on the page.
myApp.run(function($templateCache) {
$templateCache.put('buttons.html',
'<div id="other-buttons" ng-switch="data">
<div ng-switch-when="this">
<li><button>This button</a></li>
</div>
<div data-ng-switch-when="that">
<li><button>That button</a></li>
</div>
</div>'
);
});
and then load to the ng-include with
<div ng-include=" 'buttons.html' "></div>
Considering that your directive and controller share the same scope, and that your navbar falls within your controller, they should act the same.
However, if you were to use this setup in different parts of the application that do not share the same scope, I would suggest you set up a service that will bridge the gap between the two.

UI Router not working with Angular not matter what

(angularJS 1.2.5 & ui-router 0.2.7)
Please help its 4 in the morning and its been 2-3hrs since i'm stuck with this, flipped the code multiple times but cudn't make it run.
In my index.html, I have the following code:
<div class="well sidebar-nav sidebar-slide">
<ul class="nav nav-list" style="font-size:17px">
<li class="nav-header">Demand Type</li>
<li><a ui-sref="add14" data-toggle="tab">ADD-14</a></li>
<li><a ui-sref="cash_purchase" data-toggle="tab">Cash Purchase</a></li>
<li><a ui-sref="local_purchase" data-toggle="tab">Local Purchase</a></li>
</ul>
</div>
<div class="hero-unit" ui-view></div>
In my app.js, I have the following code:
var ODS = angular.module('ODS', ['ui.router','ngAnimate']);
//Define Routing for app
ODS.config(['$stateProvider', '$urlRouterProvider',
function($stateProvider, $urlRouterProvider) {
// For any unmatched url, redirect to /state1
$urlRouterProvider
.when('/add14', '/add14/create_order')
.when('/cp', '/cp/create_order')
.when('/lp', '/lp/create_order')
.otherwise("/intro");
$stateProvider
.state('intro', {
url: "/intro",
templateUrl: "templates/core/intro.html"
})
.state("add14", {
url: '/add14',
templateUrl: 'templates/core/add14.html'
})
.state("add14.create_order", {
url: "/create_order",
templateUrl: "templates/ADD14/add14.create_order.html"
})
.state("add14.own_demand", {
url: "/own_demand",
templateUrl: "templates/ADD14/add14.own_demand.html"
})
}]);
In my add14.html, I have following code:
<a ui-sref=".create_order">Create</a></button>
<a ui-sref=".own_demand">Own Demand</a>
<div ui-view></div>
In my add14.create_order.html & add14.own_demand.jsp i have sample code to print.
Thank You for your patience!
Did you ever get this figured out? I'm running into a similar problem - I find that using <a href='#/url'> seems to work, but I can't access my states via ui-sref either. I've also noticed that the rendered html doesn't auto-generate an href corresponding to the state as the documentation said it would. Fairly confused why it's not working myself.
Heads up: try to make sure you add the "ng-app" directive to your body tag (in your main template), otherwise, it seems angular-ui-router stuff, such as the ui-sref directive, will not be called.
Example:
<html ng-app="myApp">...</html><!-- Nope. Don't do this -->
<html>...<body ng-app="myApp"></body></html><!-- Do this instead -->
You are using both $stateProvider and $urlRouterProvider. try just using $stateProvider instead of both as that could be where your error is. And you don't have controllers for each of your states. Hope this helps you.

Categories