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

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.

Related

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

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.

ng-repeat not working with onsen ui

I'm going nuts, this is such a small thing but I can't find a solution...
I have this js file (the angularjs app is initialized in the begining of the html document)
app.controller('slidingMenuCtrl', function($scope) {
$scope.categories = [
{title: 'Festas', icon: 'ion-ios-pint', notifications: 3},
{title: 'Palestras', icon: 'fa-microphone', notifications: 0}
];
$scope.test = 'aaa';
});
and somewhere in my html
<ons-template id="menu.html" ng-controller="slidingMenuCtrl">
<ons-page>
<div ng-repeat="x in categories">
{{x.title}}
</div>
<div>
{{test}}
</div>
</ons-page>
</ons-template>
The div with ng-repeat shows nothing, but the one without it shows 'aaa' correctly, why?
ons-template template doesn't support ng-controller directive, basically it needs an idea to process a template and thereafter a processing if we ask for template over http it returns registered ons-template with that id, here you had menu.html
You could do same thing as that by having script tag with type text/ons-template there. Its just same as type/ng-template in angular.
Template
<script type="text/ons-template" id="main.html">
...content here...
</script>
Add ng-controller over ons-page will make it working by instantiating controller specified ng-controller directive.
Code
<ons-page ng-controller="slidingMenuCtrl">
<div ng-repeat="x in categories">
{{x.title}}
</div>
<div>
{{test}}
</div>
</ons-page>

Angular.js ng-repeat doesn't display content

I am trying to load some content using ng-repeat with Angular.js. I set up a controller which will create an array, and corresponding HTML uses ng-repeat to display all elements in the array.
HTML:
<div class="list-group" ng-controller="MainController as ctrl">
<p class="list-group-item cat" ng-repeat="element in ctrl.current_articles">{{ element }}</p>
</div>
JS:
angular.module('newsclassifier', [])
.controller('MainController', ['$http', function($http){
var self = this;
self.current_articles = [1,2,3,4,5];
}]);
Now on running this code, I am able to see that rows for 5 elements are being created in the corresponding div. However, no content is displayed.
I tried using even the $scope syntax, but to no difference. I am running version 1.4.8 of Angular.js.
Is there something amiss here?
There is a typo in your markup.
ng-controller="ctrl as MainController"
should be
ng-controller="MainController as ctrl"

Angular.js Search Query if search form is out of current file

I had this code on index.html:
<div class="container-fluid people-container">
<div class="search">
<!--Sidebar content-->
<span class="search-text">Search:</span>
<input ng-model="query" class="search-input">
<span class="sort-text">Sort:</span>
<select ng-model="orderProp" class="sort-select">
<option value="name">Alphabetical</option>
<option value="age">Date</option>
</select>
</div>
<div class="people-listing">
<!--Body content-->
<ul class="people">
<li ng-repeat="person in people | filter:query | orderBy:orderProp" class="thumbnail person-listing clearfix">
<a class="clearfix" href="#/people/{{person.id}}">
<img class="thumb" ng-src="{{person.imageUrl}}">
<div class="person-info">
<h1 class="title">{{person.name}}</h1>
<span class="year">{{person.born}} - {{person.died}}</span>
</div>
</a>
</li>
</ul>
</div>
</div>
I decided to divide the UI into partials, and moved the search part to search.html:
<div class="search">
<!--Sidebar content-->
<span class="search-text">Kërko:</span>
<input ng-model="query" class="search-input">
<span class="sort-text">Radhit sipas:</span>
<select ng-model="orderProp" class="sort-select">
<option value="name">Alfabetit</option>
<option value="age">Vitit</option>
</select>
</div>
Before doing this, the search form was working great. After I moved it to another template, it doesn't work. I have no idea because this is my first day working with Angular.js, and I'd need some help. Also, here's what on my controllers.js:
var deshmoretControllers = angular.module('deshmoretControllers', []);
deshmoretControllers.controller('PeopleListCtrl', ['$scope', 'Person',
function($scope, Person) {
$scope.people = Person.query();
$scope.orderProp = 'age';
}]);
...
Plunker:
http://plnkr.co/edit/J98O34dBFaUchhKdT6ck
i fixed the code.. there were lots of issues in it.. WORKING PLUNKER LINK
1. you need ng-controller which covers both search & results, you kept the controller on just each box & not on list
2. make sure that you ng-model never uses value without dot, rather than query - use variable as search.query
2b. make sure to initialize the search object in controller $scope.mysearch = {};
I did below modification
moved controller to list.html rather than search.html
init $scope.mysearch = {} in controller
We this is a prototypal inheritance problem.
Assuming you are moving the template and referencing it with ng-include. ng-include creates a new scope.
You set your query in the new scope, not in the parent scope that is part of PeopleListCtrl
To fix it define the query as object on the parent scope
$scope.query={term:''}
Then reference this as query in partial search.html
<input ng-model="query.term" class="search-input">
In this way the child scope can manipulate the object properties defined on parent.
As long as the parent child relationship is there you can now access the update query data in the parent scope.
Also the declaration of ng-controller=PeopleListCtrl should be on the parent element of where the search.html is inserted if used. If the controller is injected using $route definition then nothing needs to change.
Since the query has changed to object all reference should be to now query.term like
ng-repeat="person in people | filter:query.term | orderBy:orderProp"
To know more about prototypal inheritance and scopes see this wiki https://github.com/angular/angular.js/wiki/Understanding-Scopes

AngularJS ui router - not showing nested partials views

I have an AngularJs app with start up page as index.html, by default the projects view will be displayed and on top of the page I am showing a icon to show the todo items (for the logged-in user) which I am using bootstrap's data-toggle dropdown. The issue is whenever I click the todo link the partial view (todo.html) is not showing. BTW, I am new to the angular world so please forgive me if there is anything silly. Please see the code below:
Index.html
<!DOCTYPE html>
<html lang="en" ng-app="myApp">
<head></head>
<body>
<a data-toggle="dropdown" class="dropdown-toggle" ui-sref=".todo">
<i class="icon-tasks"></i>
<span class="badge badge-grey">4</span>
</a>
<div ng-view></div>
</body>
app.js
// For any unmatched url, redirect to /projects
$urlRouterProvider.otherwise("/projects");
//
// Now set up the states
$stateProvider
.state('projects', {
url: "/projects",
templateUrl: "/app/views/projects/projects.html",
controller: "projectController"
})
.state('projects.todo', {
url: "/todo",
templateUrl: "/app/views/todo/todo.html"
});
First of all replace ng-view with ui-view in the root template, cause it seems you want to use ui-router instead of ng-router.
Wrap the content of your template files with div of ui-view as a parent element.
/app/views/projects/projects.html
/app/views/todo/todo.html
<div ui-view>
... previously defined content ...
</div>
Let's say your view was
<div class="container">
<div class="page-header">
<h1>Title: {{title}}</h1>
</div>
</div
you need to add ui-view to the div
<div class="container" ui-view>
<div class="page-header">
<h1>Title: {{title}}</h1>
</div>
</div
or wrap your view with div containing ui-view descriptor in case your vie contains several tags.
I cannot show you an example since you did not provide content of view files.
/app/views/projects/projects.html
/app/views/todo/todo.html
The issue is that after fist template applying angular does not see the place to put new template anymore.
ui-router isn't really supposed to be used in this way. To integrate bootstrap with angular you want to look at UI Bootstrap - http://angular-ui.github.io/bootstrap/
Then to achieve your drop down, look at their basic examples. If you want to use separate view files to define your drop down content, you can use <div ng-include="'mycontent.html'"></div>.
ui-router is useful if you have a complex view hierarchy, where you are for example, looking for dynamic loading of children, while keeping parent states static.
In ui-router you defined all of this in the $stateProvider, so there you should define that you have a view that has another view belonging to it, example:
<!-- In index.html the main view that will have all the page views-->
<div id="main" ui-view="main"></div>
<!-- In todo.html with a partial with the dropdown code in dropdown.html -->
<h1> This is a nice todo drop down </h1>
<div id="todoDropDown" ui-view="todoDropDown"></div>
//In your app file
.state('projects.todo', {
url: '/todo',
views: {
'main#': {
templateUrl: '/app/views/todo/todo.html',
controller: 'TodoCtrl'
},
'todoDropDown#projects.todo': {
templateUrl: '/app/views/partials/dropdown.html'
}
}
})
"todoDropDown#projects.todo" This does the magic, it tells that this view has another view inside. And you can add controller to it and all other options you have in ui-router. In this way you can break up as much as possible reusable parts.

Categories