I'm trying to turn a directive into a component.
I have a value service ('path') defined on the app, which returns a path that was used to create the template url. With the directive it could be injected into the function and then used to create the template url like this:
.directive('myCustomer', [ 'path', function(path) {
return {
templateUrl: path + '/customer.html'
};
}]);
How can I pass 'path' to a component, where I have an object instead of the function?
app.component('myCustomer', {
template: `<div ng-include="$ctrl.templateUrl"></div>`,
controller: ['path', function(path) {
this.templateUrl = path + '/customer.html'
}]
});
Note: As components use isolate scope, appropriate bindings need to be added to both the component and the HTML where it is instantiated.
For more information, see AngularJS Developer Guide - Component-based application architecture.
Use component bindings to consume the value.
Refer to docs here
Thanks
Ashish
Use this.
template: '<div ng-include="$ctrl.templateUrl">'
store the value in templateUrl using component binding.
Related
I'm just learning Angular and have a very basic app set up. When rendering some data via the templateUrl property of a route, what would be the best way to include a sub-controller in the returned template? For example, including a "createOrEditItem" template at the bottom of a "viewItem" template so that the "createOrEditItem" can be reused on its own later?
I've tried putting a div in the template with its ng-controller attribute set to a controller name that I've defined at the app level, but it's not being activated. Should this be done with a directive instead to make it instantiate when the master controller has its contents set, or am I missing something more fundamental?
yes, as mentioned in the later part of the question, you should be using a directive. Or, if using AngularJS >= v1.5, component should be the choice because they are pluggable and works well with nesting too.
Note that for the route also, you can directly use a component like this:
var myMod = angular.module('myMod', ['ngRoute']);
myMod.component('home', {
template: '<h1>Home</h1><p>Hello, {{ $ctrl.user.name }} !</p>',
// ^^^^ other components can be used here
controller: function() {
this.user = {name: 'world'};
}
});
myMod.config(function($routeProvider) {
$routeProvider.when('/', {
template: '<home></home>'
});
});
Now, as the comment suggests, you can freely use other components in the template of home component.
Hope this helps a bit!
A directive can be used.
Another option is to use a seperate view/route. So when you add a ui-view tag, you could define your view and route.
This is explained here:
https://scotch.io/tutorials/angular-routing-using-ui-router
I am trying to write a simple CMS system where the content of each page is stored in a database. When the user tries to access
/pages/abc.html
through angular routing and controller to retrieve the content of that page from the database and generate abc.html on the fly. I found one way is to add a function to templateUrl to return the page:
.when('/content/pages/:name*', {
templateUrl: function(parameters) {
return '/pages/' + parameters.name + '.html';
},
controller: 'ContentCtrl',
controllerAs: 'content'
})
However the issue is I need to have abc.html already exist and then in the controller to compile the DOM content and attach it. What I am trying to do is not to have the abc.html already exist, but generated on the fly. This way I can allow my user to add xyz content and when they try to access xyz.html it will be there, without having to create xyz.html template html upfront. Is there any method I can use to achieve this.
Is there any reason you need to generate the parameters.name html file? I would think you could define the template as then pass the html into the controller. If there is a lot of repeated logic, you could make a content component or directive.
What I did for this is write a custom directive. I pass the directive an array that contain objects that correspond to ui elements. The objects are defined in JS and all have a .html() function I wrote that generates some html based on the objects properties. Then to store/restore the structure you can just JSON.stringify the object to insert it in the DB and JSON.parse to get the object back... Only tricky part is you need to store the data type as a property of the object so you can pick the right type.
The directive itself just calls the html() function on each object and concatenates the output then sets the innerHTML of the element.
I realized I could just use the template property to insert any html I want.
.when('/content/pages/:name*', {
template: function(parameters) {
return 'hello' + parameters.name;
},
controller: 'ContentCtrl',
controllerAs: 'content'
})
What you can do it pass template name as a parameter to the controller:
.when('/content/pages/:name*', {
templateUrl: function(parameters) {
return '/pages/:templateName';
},
controller: 'ContentCtrl',
controllerAs: 'content'
})
And in the controller, create the required HTML (if not existing) and then in template include the HTML using ng-include:
<div ng-include="template.url" ng-if="template.url"></div>
I'm trying to create an AngularJS slideshow app where users can add content within a projects/ directory.
The router already uses variable routes.
.when('/:project', {
templateUrl: function(params) {
return 'projects/' + params.project + '/project.html';
}
})
However, I can't figure out how to use variable Controller names. For example, the following does not work:
.when('/:project', {
templateUrl: function(params) {
return 'projects/' + params.project + '/project.html';
},
controller: function() { return 'SomeController'; }
})
But this does:
.when('/:project', {
templateUrl: function(params) {
return 'projects/' + params.project + '/project.html';
},
controller: 'SomeController'
})
Is it possible to associate a controller with a route using a function?
If this sounds like a silly idea, let me explain what I'm trying to do. Instead of having user's edit the MainController, I'd like to be able to write JavaScript specific to a project. If a project gets deleted, that project's specific JavaScript is also deleted. If a new project gets added that needs custom JavaScript, users can use an API (AngularJS Events) to interact with the UI.
What's the best way to do something like this?
UI Router has controllerProvider feature. ngRoute doesn't have it.
The function specified in route controller is actual controller constructor, it can't just return controller name. It is ngView directive that defines how route controllers are instantiated. Without patching the directive the behaviour can be simulated with:
controller: function ($scope, $controller) {
return $controller('SomeController', { $scope: $scope });
}
I'm working with a directive.
Here is simple format of my directive:
angular.module('app',[]).directive('companylookup', CompanyLookupDirective);
function CompanyLookupDirective() {
return {
templateUrl: '<input id="foo"/>',
controller: 'CompanyLookupController',
controllerAs: 'vm'
}
}
I want to find input element with jquery in my controller (CompanyLookupController.js) like this:
var foo = $('#foo');
// decorate foo element using igniteui lib
$('#foo').igCombo({ datasource: ...});
But $('#foo') always return null. I can try to delay finding element with $timeout service to wait until element exist. But I don't want to do this so much times in my app in concern of performance.
Is there any way we can reference template elements in angularjs from a controller?
in template URL use escape character before quotes ,
templateUrl: '<input id=\"foo\"></input>'
Also i agree with #Robert Goldwein and if you absolutely have to, use link to manipulate DOM
EDIT : Help on link and compile functions.
I want to show a laravel blade view file in angular JS directive by
var commentsApp = angular.module('CommentApp',[]);
commentsApp.directive('commentForm',function(){
return {
restrict: 'EA',
replace: 'true'
templateURL: 'views/comments/comment-form.blade.php'
}
});
I want to use it by angular directive instead of
#include('comments.comment-form')
Where is my problem? How to solve this.
Thank you.
First you must define a route in laravel
Route::get('comment-form', function() {
return view('comments.comment-form');
});
Then you can use it in AngularJS
var commentsApp = angular.module('CommentApp', []);
commentsApp.directive('commentForm', function() {
return {
restrict: 'EA',
replace: 'true',
templateURL: 'comment-form'
}
});
Answer above is a good idea, however i dont like the idea of asking for a template by routing, We would create a route for each component :c . I leave my solution here:
In gulpfile.js inside elixir function add this line:
var elixir = require('laravel-elixir');
elixir(function(mix) {
mix.copy('resources/assets/js/angular/components/**/*.template.html', public/angular-templates');
//Find all files with suffix .template.html
});
As you notice it, i created a folder called 'angular' and then another one called 'components', there we will have our components
Angular-----------------------------
--Components------------------------
----my-component.directive.js-------
----my-component.template.html------
We have to create a global angular variable taking our browser window origin (www.myapp.com, localhost:8000, etc) by doing:
angular.module('myModule',[])
.value('pathAssets', location.origin + '/angular-templates/')
In our templateUrl we will call the template by writting:
templateUrl: pathAssets + '../angular-templates/my-template.html',
I have to say we have to concat our angular files in a file, otherwise it won't work D: if you don't know how to do it, add these lines in your gulpfile.js
mix.scripts([
'../../../bower_components/angular/angular.min.js',
'angular/app.js',
'angular/controllers/**/*.controller.js',
'angular/components/**/*.directive.js',
'angular/bootstrap.js',
], 'public/js/app.js'); //We concatenate angular files saving them in app.js
Finally execute the command 'gulp' in terminal(In our project), it should generate a new folder in public called angular-templates.
That's it :)
(function(angular) {
'use strict';
angular.module('app').component('bringTeamToEvent', {
templateUrl: '/assets/ng/app/team/bringTeamToEvent.html',
bindings: {
hero: '='
}
});
})(window.angular);
Just work from the public directory, no need to compile assets and move if you dont need to.
Then add the # symbol to tell blade to ignore and let angular do its work within the template
<span>Name: #{{ $ctrl.hero.name}}</span>