is it possible to create a AngularJS Component with a dynamic templateUrl?
Means I want to inject a service into the Component that gives me a base path to the template:
i.e.: templateUrl: configuration.baseScriptPath + '...html'
It is possible with a Directive, but how to do this with a Component?
angular.module('runtime')
.component('textInput', {
templateUrl: /*configuration.baseScriptPath + */'fd/components/text_input_instance.html',
controller: [
'$scope', '$element', 'focusInputGroup', 'configuration',
function ($scope, $element, focusInputGroup, configuration) {
Instead of templateUrl you can use template and ng-include, like this:
angular.module('runtime')
.component('textInput', {
template: '<div ng-include="getTemplate()">',
controller: [
'$scope', '$element', 'focusInputGroup', 'configuration',
function ($scope, $element, focusInputGroup, configuration) {
$scope.getTemplate = function () {
return configuration.baseScriptPath + 'fd/components/text_input_instance.html';
};
templateUrl property of component also takes a function. so you can try this,
angular.module('runtime')
.component('textInput', {
templateUrl: ['$configuration', function($configuration) {
return $configuration.basepath + '.html'
}],
controller: [
'$scope', '$element', 'focusInputGroup', 'configuration',
function($scope, $element, focusInputGroup, configuration) {
Related
I'm trying to setup one of my first angular projects and am having trouble getting to grips with the routing.
On page load I see the initial template that has been set by the preferencesDirective, which is great.
When I click the "Change Template" button I want it to change to another template but nothing happens. If I set the template url's in the $routeProvider to something invalid then I see a 404 error in the debugger which tells me something must be working but nothing happens when the template url is valid.. How do I get it to change correctly?
Thanks.
<div id="PreferencesApp" class="" ng-app="clientPreferencesModule">
<preferences-directive factory-settings="clientPreferences"></preferences-directive>
Change Template
</div>
<script>
var app = angular.module("clientPreferencesModule", ["ngResource", "ngRoute"]);
//var app = angular.module("clientPreferencesModule", ["ngRoute"]);
app.config(function ($routeProvider) {
$routeProvider.when("/", { controller: "clientPreferencesController", templateUrl: '/AngularTemplates/ClientPreferences/PreferencesTemplate.html' });
$routeProvider.when("/Preferences/:id", { controller: "clientPreferencesController", templateUrl: '/AngularTemplates/ClientPreferences/PreferencesTemplate.html' });
$routeProvider.when("/Preferences", { controller: "clientPreferencesController", templateUrl: '/AngularTemplates/ClientPreferences/PreferencesTemplate.html' });
$routeProvider.when("/Details", { controller: "clientPreferencesController", templateUrl: '/AngularTemplates/ClientPreferences/DetailsTemplate.html' });
});
app.controller('clientPreferencesController', clientPreferencesController);
clientPreferencesController.$inject = ["$scope", "$resource", "$rootScope", "$http", "$route", "$location"];
function clientPreferencesController($scope, $resource, $rootScope, $http, $route, $location) {
this.model = #Html.Raw(JsonConvert.SerializeObject(Model));
$scope.location = $location.path();
}
app.directive('preferencesDirective', preferencesDirective);
function preferencesDirective() {
return {
restrict: 'EA',
scope:
{
factorySettings: '='
},
controller: 'clientPreferencesController',
controllerAs: 'pc',
bindToController: true,
templateUrl: '/AngularTemplates/ClientPreferences/PreferencesTemplate.html'
}
}
</script>
For routing to work you've to create different views along with its associated controller & then have directive inside that view. And also you'll need ng-view directive in index.html in which all the routes view going to be loaded. And also preferencesDirective should only contain the reusable unique functionality, & the complete app view, so that you can have it different views with different data sets alongside different view components.
So, your template can be:
<div id="PreferencesApp" class="" ng-app="clientPreferencesModule">
Change Template
<div ng-view></div>
</div>
Now for different routes you can have each different controllers or if you want to handle it in one controller the have only one, but different from directive's controller, so it can be,
app.config(function ($routeProvider) {
$routeProvider.when("/", { controller: "viewController", templateUrl: '/AngularTemplates/ClientPreferences/PreferencesTemplate.html' });
$routeProvider.when("/Preferences/:id", { controller: "viewController", templateUrl: '/AngularTemplates/ClientPreferences/PreferencesTemplate.html' });
$routeProvider.when("/Preferences", { controller: "viewController", templateUrl: '/AngularTemplates/ClientPreferences/PreferencesTemplate.html' });
$routeProvider.when("/Details", { controller: "viewController", templateUrl: '/AngularTemplates/ClientPreferences/DetailsTemplate.html' });
});
Have preferencesDirective in all these templates. (This will now potentially change the directive's template but you can have changing dom of each view in views's templates & keep directive's template constant)
Now in viewController by making use of $routeParams you can check the current route & send different data to preferencesDirective's controller.
Now if you must want to change directives template conditionally then make use of ng-include inside directive's template.
function preferencesDirective() {
return {
restrict: 'EA',
scope:
{
factorySettings: '=',
templateSrc: '='
},
controller: 'clientPreferencesController',
controllerAs: 'pc',
bindToController: true,
templateUrl: '<ng-include src="pc.template()"></ng-include>'
}
}
function clientPreferencesController($scope, $resource, $rootScope, $http, $route, $location) {
this.model = #Html.Raw(JsonConvert.SerializeObject(Model));
$scope.location = $location.path();
$scope.template = function(){
if($scope.templateSrc) {
return '/AngularTemplates/ClientPreferences/'+ $scope.templateSrc + '.html';
}
}
}
Here share that templateSrc from viewController based on current route.
I'm trying to pass the parameters to the AngularJS controller.
AngularJs Routes
$routeProvider.when('/post-ads/', {
templateUrl: "ui/view/post-ads.php",
controller: "adPostController",
controllerAs: 'vm'
})
$routeProvider.when('/post-ads/:category/:subcategory', {
templateUrl: "ui/view/ad-details.php",
controller: "adPostController",
controllerAs: 'vm'
})
AdPostController
adPostController.$inject = ['ApiService', '$scope'];
function adPostController(ApiService, $scope, $routeParams) {
console.log("im here");
console.log($routeParams.category, $routeParams.subcategory);
}
HTML a href
<a href="#/post-ads/automobile/car>click</a>
Error
TypeError: Cannot read property 'category' of undefined
I guess your have to change:
adPostController.$inject = ['ApiService', '$scope'];
function adPostController(ApiService, $scope, $routeParams) {
console.log("im here");
console.log($routeParams.category, $routeParams.subcategory);
}
To:
adPostController.$inject = ['ApiService', '$scope', '$srouteParams'];
function adPostController(ApiService, $scope, $routeParams) {
console.log("im here");
console.log($routeParams.category, $routeParams.subcategory);
}
Change to this:
adPostController.$inject = ['ApiService', '$scope', '$routeParams'];
I have been trying to redirect my application to the following link using
$location.path('/enterprise/update/' + enterprise.id);
The current url when I click the button is http://localhost:8080/#/enterprise/view
and I would like it to be changed to http://localhost:8080/#/enterprise/update/0
(The 0 here represents the id)
The edit function is the one which is called when I click on the button to redirect.
Relevant code:
EnterpriseCtrl.js
app.controller('EnterpriseCtrl', ['$scope', 'Enterprise', '$location','$http','$route','$routeParams','$resource', function($scope, Enterprise, $http, $route, $location, $rootScope) {
$scope.enterprises = Enterprise.list({}, function (response) {
return response;
});
$scope.add = function(){
Enterprise.save($scope.enterprise,function (){});
$scope.enterprise = null;
};
$scope.delete = function(enterprise, index){
alert("Do you really want to delete an Enterprise at index " + (index+1) + "?");
//book.$remove();
Enterprise.remove(enterprise);
$scope.enterprises.splice(index, 1);
};
$scope.edit = function(enterprise){
console.log(enterprise.id);
console.log(location);
console.log($location);
$location.path('/enterprise/update/' + enterprise.id);
};
// $scope.enterprise = Enterprise.get({id: $route.current.params.id});
$scope.update = function(){
Enterprise.update($route.current.params.id);
$location.path($rootScope.history.view);
};
}]);
app.js
var app = angular.module('mpsApp', ['ngRoute','ngResource']);
app.config(['$routeProvider','$locationProvider',
function ($routeProvider,$locationProvider) {
$routeProvider.
when('/', {
templateUrl: 'home.html'
}).
when('/enterprise/view', {
controller: 'EnterpriseCtrl',
templateUrl: 'showEnterprise.html'
}).
when('/enterprise/add', {
controller: 'EnterpriseCtrl',
templateUrl: 'addEnterprise.html'
}).
when('/enterprise/update/:id', {
controller: 'EnterpriseCtrl',
templateUrl: 'updateEnterprise.html'
}).
otherwise({
redirectTo: '/'
});
}
]);
The error that I get is
TypeError: $location.path is not a function
at Scope.$scope.edit (EnterpriseCtrl.js:29)
at $parseFunctionCall (angular.js:12330)
at callback (angular.js:22940)
at Scope.$eval (angular.js:14381)
at Scope.$apply (angular.js:14480)
at HTMLButtonElement.<anonymous> (angular.js:22945)
at HTMLButtonElement.eventHandler (angular.js:3009)
Your dependency injection array/parameters are out of order. Should be:
[ '$scope', 'Enterprise', '$location', '$http', '$route', '$routeParams', '$resource',
function($scope, Enterprise, $location, $http, $route, $routeParams, $resource) {
Note, how each single array element service corresponds to the parameters in the function.
I have created a directive inside my controller, which i want to include another controller to the directive. The error i get back is Error: [ng:areq] Argument 'js/controllers/testview/DocumentController.js' is not a function, got undefined
TestviewController
app.controller('TestviewController', ['$http', '$scope', '$sessionStorage', '$state', '$log', 'Session', 'api', function ($http, $scope, $sessionStorage, $state, $log, Session, api) {
var module_id = $state.params.id;
$http.get(api.getUrl('componentsByModule', module_id))
.success(function (response) {
$scope.components = response;
});
}]);
app.directive('viewDoc', function () {
return {
templateUrl: "tpl/directives/testview/document.html",
controller: "js/controllers/testview/DocumentController.js",
resolve: { components: function() { return $scope.components }}
};
});
DocumentController
app.controller('DocumentController', ['$http', '$scope', '$sessionStorage', '$state', '$log', 'Session', 'api', 'components', function ($http, $scope, $sessionStorage, $state, $log, Session, api, components) {
$scope.components = components;
}]);
I'm pretty new with directices, but does anyone have any idea what I'm doing wrong?
Inside the directive definition object, the controller property expects a string with the function name, or the function itself (not the path to script file).
app.directive('viewDoc', function () {
return {
...
controller: "DocumentController",
};
});
You want to call the controller by name, not by file name:
controller: "js/controllers/testview/DocumentController.js"
should be
controller: "DocumentController"
There is no option to put controller by its URL in the directive definition. However if you define your controller in DOM template you could use controller: 'myController as myCtrl' in directive definition
are you sure you need a directive controller? i think what you are trying to achieve is link function.
you can use directive link functions like controllers.
.directive('myDialog', function() {
return {
restrict: 'E',
transclude: true,
scope: {},
templateUrl: 'my-dialog.html',
link: function (scope, element) {
scope.name = 'Jeff';
}
};
});
take a look at angular docs
https://docs.angularjs.org/guide/directive
I have multiple routes that invoke the same Controller and I would like to pass different variables to it.
// Example
$routeProvider.
when('/a', {
templateUrl: 'test.html',
controller: 'MyController' // should get passed 'exampleA'
}).
when('/b', {
templateUrl: 'test.html',
controller: 'MyController' // should get passed 'exampleB'
});
I know that I could use the "resolve" object:
$routeProvider.
when('/a', {
templateUrl: 'test.html',
controller: 'MyController',
resolve: {test: function() { return true; }}
});
To pass a value as a dependency:
app.controller('MyController', ['$scope', 'test', function ($scope, test) {
console.log(test); // true
}
My problem with that approach is that my app crashes if the resolve object is missing on other routes and I would like to pass optional params.
Is there any way to pass specific params to the Controller (from the route provider)?
Thank you
Routing:
$routeProvider.
when('/a', {
templateUrl: 'test.html',
controller: 'MyController',
paramExample: 'exampleA'
}).
when('/b', {
templateUrl: 'test.html',
controller: 'MyController',
paramExample: 'exampleB'
});
Access: inject $route in your controller then use this
app.controller('MyController', ['$scope', '$route', function ($scope, $route) {
var paramValue = $route.current.$$route.paramExample;
console.log(paramValue);
}
You can use resolve and $route.currrent.params.test to pass the parameter like this:
$routeProvider
.when('/a', {
templateUrl: 'view.html',
controller: 'MainCtrl',
resolve: {
test: function ($route) { $route.current.params.test = true; }
}
})
.when('/b', {
templateUrl: 'view.html',
controller: 'MainCtrl',
resolve: {
test: function ($route) { $route.current.params.test = false; }
}
})
Then in your controller you can access it from the $routeParams:
app.controller('MainCtrl', function($scope, $routeParams) {
$scope.test = $routeParams.test;
})
http://plnkr.co/edit/ct1ZUI9DNqSZ7S9OZJdO?p=preview
The most natural way to do this is doing what you would normally do when you want to load a page with parameters: use query parameters: http://yoururl.com?param1=value¶m2=value
ngRoute comes with the service $routeParams which you can inject in your controller. Now you can simply retrieve the values like this $routeParams.param1.
Another way to do this is to retrieve the path with $location.path and set the variable there.
using $routeParams
in Main js file
routeApp.config(function($routeProvider) {
$routeProvider
.when('/home', {
templateUrl: '../sites/./home.html',
controller: 'StudentController'
})
.when('/viewStudents/:param1/:param2', {
templateUrl: '../sites/./viewStudents.html',
controller: 'StudentController'
})
.otherwise({
redirectTo: '/'
});
});
routeApp.controller('StudentController',['$filter','$routeParams', '$location',function($filter,$routeParams,$location){
var StudentCtrl = this;
StudentCtrl.param1 = $routeParams.param1;
StudentCtrl.param2 = $routeParams.param2;
}]);
calling from Home.html
<div class="container">
<h2> Welcome </h2>
Students
</div>