I want to preload a template in my div using ui-router.
This is my template.html file which is located in /templates folder.
// its location is templates/template1.html
<div>
Template 1
</div>
The .config function in angularjs has the following code which includes the states. Here template1 is the child state of the state1
.state('state1',{
url:'/state1',
templateUrl:'templates/state1.html',
controller: 'state1Controller',
})
.state('state1.template1',{
templateUrl: 'templates/template1.html'
})
Template1 is loaded when i press a button, but i want the template to be preloaded. What can i do to attain my desired result?
Declarative way: Put all your template into a script tag with type as text/ng-template:
<script type="text/ng-template" id="templateId.html">
<p>This is the content of the template</p>
</script>
Code way: Use $templateCache for this.
In state1Controller, load your template and put it into cache like this:
$templateCache.put('templateId.html', 'This is the content of the template');
Or load it with http:
$http.get('templates/template1.html').then(function(template){
$templateCache.put('templateId.html', template);
})
Then in your router definition, put templateId.html as value of templateUrl
.state('state1.template1',{
templateUrl: 'templateId.html'
})
and any time you request templateId.html, angular will automatically find template in $templateCache before sending request to server.
Related
Imagine we have an AngularJs app (witten in multiple controllers, services, directive and run method) for multiple routes using $routeProvider. and now we need to use the same application in a single page. meaning that templates of different routes should now be visible in one page at the same time.
I can't use different iframes because then it's hard to access the $scopes of those controllers from the wrapper application.
Is this possible without the use of iframes?
What you are looking for is ng-include and ng-controller. Using ng-include, You can insert a html into the block containing it and using ng-controller, you can insert a controller for the same block. I would prefer not to use iframes as it is a bad practice and you will not be able to access scope and a lot of features that are native to angular.
EDIT : Since, you are using the run() function you can try the below approach :
Keeping the routeProvider same, you can move the contents of you html template files into script tags on you index.html like so :
<script type="text/ng-template" id="one.tpl.html">
//Your html template code goes here
</script>
<script type="text/ng-template" id="two.tpl.html">
//Your html template code goes here
</script>
In you app.js :
$routeProvider.
when('/', {
templateUrl: 'one.tpl.html', //points to the content of the script tag in your index.html file
controller: 'onetplCtrl'
}).
when('/edit',{
templateUrl:'two.tpl.html', //points to the content of the script tag in your index.html file
controller:'twotplCtrl'
}).
otherwise({
redirectTo: '/'
});
Like in title, I can't load a template correctly. I can't understand where the problem is, the only error that I got is "Error: [$compile:tpload] Failed to load template: /testingBlock.html"
Paths:
/mainDirOfTheProject
/application
/library
/webroot
/javascript: [angularjs.js, angular-route.js, app.js]
index.html
testBlock.html
HTML(index.html):
<body ng-app="App" ng-controller="MainCTRL as ctrl">
{{ctrl.nameApp}}
<div ng-view></div>
</body>
HTML(testingBlock.html):
<h1>Just a test</h1>
Javascript (app.js):
angular
.module("App", ["ngRoute"])
.config(config)
.controller("MainCTRL", MainCTRL);
function MainCTRL($location){
this.nameApp = "myApp";
}
function config($routeProvider, $locationProvider){
$routeProvider
.when("/",{
templateUrl: "/testingBlock.html",
controller: "MainCTRL"
})
.otherwise({redirectTo:"/"});
$locationProvider.html5Mode({enabled:true, requireBase:false});
}
I sorted it out: the problem was that the routing doesn't accept HTML file but HTM file.
I tried with jQuery ajax call, and it was the same.
So the question is, why jQuery ajax call doesn't accept .html files?
Try to use a dot in front of the slash :
templateUrl: "./testBlock.html",
Should be able to load it relative to the path of your main index.html, try:
templateUrl: "testBlock.html",
If that doesn't work, watch the network tab in your browser dev tools and see what path it's trying to load your template from, and adjust as needed.
[EDITED] My app has the following structure:
index.html
<body ng-app = "myApp" ng-controller ="mainController">
<ng-view></ng-view>
</body>
mainView.html (loaded into ng-view through routeProvider in app.js)
<div ng-include src="subview1">
<div ng-include src="subview2">
subview1 and subview2 are set within mainController (mainView's controller) as scope variables:
$scope.subview1= "templates/subview1.html";
$scope.subview2= "templates/subview2.html";
controller1 and controller2 are subview1 and subview2's controllers.
subview1.html (loaded in first div of mainView)
<div ng-controller="controller1">
<button ng-click="loadNewView()"></button>
</div>
controller1.js
.controller('controller1', function($scope){
$scope.loadNewView = function(){
$scope.$parent.subview1 = "templates/view3.html";
}
}
scope.loadNewView should load a different view (and relative controller) within the div with src="subview1" in mainView.html). Basically it's about refreshing the view itself by raplacing it with another view (and related controller).
I use $parent to update the view in subview1's parent view (i.e. mainView).
however nothing happens and if I try to use $scope.$apply() I get error (digest already in progress).
Any clue?
you can try something like this...
In your stateProvider or in your routeProvider if you using.
var mod = angular.module('example.states', ['ui.router']);
mod.config(['$stateProvider', '$urlRouterProvider',
function($stateProvider, $urlRouterProvider) {
$stateProvider
.state('exampleState', {
url: '/main',
templateUrl: 'mainView.html',
controller: mainController
});
}
]);
return mod;
So here you have associated your parent controller(let's say the mainController which will be the parent of all others) with its template mainView.html.
Then in your mainView.html,Load all the subview templates.
<div ng-repeat="template in templates">
<ng-include src="template.url"></ng-include>
</div>
templates is an array in your mainController which has the url or path of all your subtemplates.When you use ng-include inside the main template then all subTemplates will automaticlly become the child of the mainTemplate and its Controllers too.In a way it will inherit from the parent Controller.
So suppose if subView1.html is one of the template url you had given in ng-include.Then it will look like
<div ng-controller="subView1Controller">
//Here your code
</div>
And subview2 as
<div ng-controller="subView2Controller">
//Here your code
</div>
This way you will have multiple views on the same page with one url and different controllers with its associated templates and each will inherit from the parent controller which is mainController here.
There, might be better approach than this.
This is what i had used in my project,and its simple to keep your code simple manage.
Okay,so using routeProvider,you can use it like this
var app = angular.module("app",[]);
app.config(function($routeProvider){
$routeProvider
.when('/main',{
templateUrl:"mainView.html",
controller:mainController
})
});
app.controller("mainController",function($scope){
});
app.controller("subView1Controller",function($scope){
});
app.controller("subView1Controller",function($scope){
});
Then in your mainView.html,Load all the subview templates.
<ng-include src="yoursubtemplate1path"></ng-include>
<ng-include src="yoursubtemplate2path"></ng-include>
And then in yoursubtemplate1 use
<div ng-controller="subView1Controller">
//Here your code
</div>
Same for the other templates.
You can set the template src of the subtemplates from your mainController.
app.controller("mainController",function($scope){
$scope.templatesrc="/app/template1.html";
});
And then use it in your template,where you are using ng-include directive.
<ng-include src="templatesrc"></ng-include>
Its better to store template url's in an array and use ng-repeat directive like i had stated before,if you are loading more templates.
And if you want to show the div on some button click lets say in parent controller then use ng-if in the sub-view main and make it true on button click.
This answer is regarding your updated question.
The solution which you had used before,will load all temlplate and once in ng-include and its associated controller making the mainController as parent.
But if you want to load a different view with its newController then you can try something like this.
Just add one more route and call on your event click,but remember this newView's Controller will have no parent-child relation with the mainView's controller.
var app = angular.module("app",[]);
app.config(function($routeProvider){
$routeProvider
.when('/main',{
templateUrl:"mainView.html",
controller:mainController
})
.when('/anyName',{
templateUrl:"templates/view3.html",
controller:temp3Controller
})
});
And in your controller1.js
.controller('controller1', function($scope){
$scope.loadNewView = function(){
$location.path('/anyName');
}
}
Inject location service in controller1.
I finally found the solution.
The tricks is using
$scope.$parent.$parent.subview1 = "templates/view3.html";
instead of
$scope.$parent.subview1 = "templates/view3.html";
since, basically:
ng-include is the child of mainView
subview1 is the child of ng-include
root html:
<html> stuff <div ui-view></div> stuff </html>
partial template
<div class="article-view">
{{date_published}}
</div>
When I navigate using $state.go('root.' + entryStateUrl); the url changes but new state's content (template) is appended right after root's state content. I need to show template on new clean page. How to do it?
Maybe similar to this SO.
Edit
I generated and attached states like this:
$stateProviderRef.state('root.' + generatedStateName,
{ url: 'root/' + generatedStateName,
templateUrl : 'partials/article-view.html',
controller: function($scope){
$scope.date_published = data.date_published;
}
});
UPDATE
When I changed it like this it stopped working:
$stateProviderRef.state(generatedStateName,
{ url: generatedStateName,
templateUrl : 'partials/article-view.html',
controller: function($scope){
$scope.date_published = data.date_published;
}
});
Redirecting to a new page means you won't be able to bind to the controller used from the origin page, since the redirected page won't have any attachment to your js code.
What I want to do is to load separated templates and append a controller to each one:
an approach:
$http({
method: 'GET',
url: 'templates/myTemplate.html',
controller:'myCtrl'
})
function myCtrl($scope){
$scope.var1= "scoped variable";
}
myTemplate.html:
A Tag
{{var1}}
that is an aproach to this question:
Loading an AngularJS controller dynamically
It appears that your scenario would be a good place to apply ng-include. For example, given this markup:
<div ng-controller="MainCtrl">
<div ng-include="template"/>
</div>
and this code in MainCtrl:
function MainCtrl($scope) {
// some logic that would determine the template you want to load
$scope.template = 'templates/myTemplate.html';
}
and this code in templates/myTemplate.html:
<div ng-controller="TemplateCtrl">
<!-- Template Content -->
</div>
angular will automatically download templates/myTemplate.html and apply TemplateCtrl to the template. (Of course you'd also need to have TemplateCtrl defined.) When you want to switch templates, in MainCtrl you'll need to change the value of $scope.template to another template url; that template would specify an ng-controller attribute that indicates the appropriate controller for that template.