Loading partial html template into Angular app using Laravel - angularjs

I'm trying to use the RouteProvider functionality in Angular. A different partial html template should be loaded depending on whether the user is editing a form, viewing a list of completed entries, etc. I've been unable to load the html templates within the same page. Instead, the user is redirected to a different page.
Here's the relevant Angular code:
.when(/new', {
controller: 'CreateCtrl'
templateUrl: 'partials/newform.html'
The Laravel Route:
Route::resource('services', 'ServicesController');
The newform.html file is located at resources/views/partials/newform.html within Laravel.
Any thoughts on how I can load these partial html templates from Laravel?

One way would be to reference the full path to the partials
.when('/new', {
controller: 'CreateCtrl'
//depending on your path adjust it
templateUrl: 'partials/newform'
since you are just using .html not tempalte.blade.php file for template you should move it to public folder.
Update:
If you really dont want to move the template out of view folder of laravel
create a route and serve your html from there
Route::group(array('prefix' => 'partials'), function(){
Route::get('/newform', function()
{
return File::get(app_path().'Views/partials/angular.html');
});
});
Note: I will suggest you not to mix Laravelc template with Angular, keep Laravel as REST API, and your Angular should separate layer.
Here are some Pros and Cons for both approach

I found another way using gulp, i leave my solution :)
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.
CONCLUSION
1. Move all your angular templates to public inside a specific folder by using elixir.
2. create a global variable in angular to save your origin URL and use it in your directives it automatically with this template in public.

Related

Scripts multiplies in controllers

I'am using node.js with sails.js for backend and angular.js for frontend.
In angular i am using one main controller and some childs conrtoller.
As you know, by default in sails.js, in file layout.ejs included all java scripts and css files between tags
<!--SCRIPTS--><!--SCRIPTS END-->
and
<!--STYLES--><!--STYLES END-->
Main content are included to <%- body %> tag
When i am lifted sails, go to browser and inspect "elements" i see some problem:
main controller (let it be "myApp") in angular generating html by using layout.ejs like main body (with all css and js), and then included controllers content.
Now problem:
Problem is that another child controllers of "myApp" generating by using layout.ejs too. And thats why some scripts included multiple times.
Example: 4 child controllers = 4 included of google.maps.api. Thats bad!! code so dirty!
And now question: how i can fix this issue, and make scripts and css included just one time?
Create another layout let's call it views/blanklayout.ejs with just this content:
<%- body %>
Now, use this layout with all child controller views.
Do either
In your sails controller set layout to blanklayout: res.locals.layout = 'blanklayout';
OR you can also specify layout in routes e.g.
'GET /test': {
controller: 'TestController',
action: 'test',
locals: {
layout: 'blanklayout',
},
},
PS: You can swap layouts also, meaning have just <%- body %> in layout.ejs and another layout (e.g. mainLayout.ejs to contain present content of layout.ejs. That way you'll not have to specify to use mainLayout only for main controller view.

How to organize routes for user and admin in angular separately

I am working on an Angular & Node app. My all view files are stored in public and I created a middleware to access the static file as below:
app.use(express.static(__dirname+ "/public"));
Now, When I run my app,localhost://3000/#/, first of all index.html file is executing where only header and footer are placed and then the ng-view part.
Now I want to know, where I have to place my admin html files so that I can access the url like as localhost://3000/#/admin/dashboard.
Even User view layout is different from adminlayout.
How to organize user admin view files and their routes?
first create a admin.view.html file in (public/views). Then call the admin.view.html to the app.js inside the same folder public (like this way in app.js)
.config(['$routeProvider', function($routeProvider) {
$routeProvider.
when('/admin', {
templateUrl: 'views/admin.view.html',
controller: 'AdminCtrl'
})
After that make a new folder(controller) in same folder public and make a file admin.controller.js. and then come out of folder and in the routes folder make a file admin.js. if you got from this its good or just give your emailid i wil mail you a project made by me on angular and node which will may help you
Basically, with the application like that, you must have something called "permission" on each URL.
But for the specific case like you mentioned above. You can use ng-if condition directive to show which you want to show in each view (admin/user).
You do not need to separate user.html file and admin.html file.
You just need an index.html with the layout inside it. (Admin or user must have the same layout page right?). You should separate this view to multiple angular module (menu bar, tabs, toolbar ...) and use ng-if to show which you want to show.
to call admin layout you should this hope this will work for you
.config(['$routeProvider', function($routeProvider) {
$routeProvider.
when('/admin', {
url: '/admin',
templateUrl: 'views/admin/layout.html'
}).
when('admin.login', {
url: '/admin/login',
templateUrl: 'views/admin/login.html',
controller: 'AdminLoginCtrl'
})
Then you need to create this new Layout Pages. On: views/admin/layout.html
<div>
<ui-view/>
</div>
and similars for others...

dynamic templates/theming system for Angular app

I am trying to create a nice dynamic theming system in my angular app.
Basically I have a Wordpress plugin which you pick via a dropdown which theme you want for my Angular app (which is on the same server in a subfolder), and I pass along the theme via a GET param, www.mywebsite.com/myapp/welcome?theme=white_theme, and the angular app in that folder currently will quickly set in the frontcontroller (think I will move this into an app.js resolve for the route so it happens before the controller, right now I just have the resolve setting a default theme):
var dynamic_theme = URI.parseQuery(query_string).theme; //url param gotten via URI js library
if(dynamic_theme) {
$rootScope.theme_name = dynamic_theme;
} else {
$rootScope.theme_name = 'default';
}
and later on in the index.html i include the dynamic theme via ng-href:
<!-- build:css(.tmp) styles/generic.css -->
<link rel="stylesheet" href="styles/generic.css">
<!-- endbuild -->
<link rel="stylesheet" ng-if="theme_name" ng-href="styles/themes/{{theme_name}}/main-theme.css">
But I also want the .html templates themselves to be able to be overwritten by our design theme for each theme.
For example, in app.js, to start off this 'questionnaire' app I have this defined:
templateUrl: 'views/main.html',
and in that file, i have a directive:
That directive uses the template 'views/question.html'
which inside of that file I decide whether to get 'views/templates/radio.tpl.html', 'views/templates/checkbox.tpl.html', 'views/templates/dropdown.tpl.html' based on the question-type passed to the directive.
like so:
<div ng-include src="'views/templates/' + currentquestion.question_type + '.tpl.html'"></div>
I guess maybe I can pass the theme into the directive (or just have access to the $rootScope) and do something like so:
<div ng-include src="'views/templates/' + dynamic_theme + '/' + currentquestion.question_type + '.tpl.html'"></div>
I was just curious if that sounds like a plan. or is there a better way to do this (or even a real theming resolver library/setup you can use for Angular that does the same things that I'm trying to achieve manually).
There seem to be a number of different ways to do this, the most promising looks to be using templateUrl as a function:
templateUrl: function(elem,attrs){
return 'views/templates/' + resolveTheme() + 'main.tpl.html';
},
You would have to write resolveTheme() yourself, possibly as a global or a service.
Alternative
Another option, if you can precompile your templates you can use the $templateCache and dynamically load the right template pack. You'd need to make sure this happened before any of the templates were requested as angular will make an HTTP request for any templates that it can't already find.
Here is one way to pre-compile your templates:
https://github.com/karlgoldstein/grunt-html2js
You could then have multiple template packs: template-theme1.js, template-theme2.js
And either build multiple versions of the app or include these templates after your application code (but before any templates get requested).

How to deal with templates of completely different areas (but same website) with AngularJS

I have a webapp with a main index.html that shows each page through an ng-view and a routeProvider.
Now I'm adding an entry page for users who are still not logged in. This page could also have his own ng-view to slide different sections for non logged users (welcome, what is, sign in, sign up ecc...) and his own head with css scripts ecc...
I'd rather that both the webapp index and the entry page index address to www.example.com (so nothing like www.example.com/welcome ).
I thought about a structure similar to this:
webapp/
main/
page1/
page2/
welcome/
section1/
section2/
index.html
welcome.js (angular module for the entry page)
.htaccess
index.html
webapp.js (angular module containing the routeProvider for the webapp)
Currently I have that .htaccess that rewrites all the fake queries to index.html so that everything is handled here.
So in particular:
1) How can I say to the routerProvider of webapp.js to go to /welcome/index.html when the user is not logged in, if I already use this condition for the webapp main page? (Should I use the run method? a brief example will be helpful)
.config(['$routeProvider', function($routeProvider){
$routeProvider
.when(...)
.when('/', {
templateUrl : 'main/webapp-main.html'
})
.when(...)
2) How do I prevent that everything in welcome/index.html will be loaded within the index.html ng-view? (maybe using ng-if to hide ng-view? or there is some way to control this behavour with the routerProvider?)
3) There is a better and simpler way to achieve all of this?
Thanks.
Update:
Ok I think there was an underlying problem in my question... I can't use a complete different page since everything is loaded in and switching to another page will cause the reload of the app loosing all the data.
So I suppose I should use the same main template for the entire website.
Then I add: there is a way in angularjs to load different style sheets dynamically?
this questions is old but i think is valid and can clarify someone a few thinks.
First of all you are suppose to use a single page for AngularJS apps, otherwise you will have to do something like a redirect link, and in your other-index.html load an entirely different Angular Application also loading every script needed in the first one.
1) Use ui-router is easy to work, and very robust, the only thing you need to have is a container for your ui-view then the ui-router will fill the container with the corresponding html
2) To prevent navigation you should do something like this:
angular.module('myApp', [])
.run(function($rootScope, mySessionService){
$rootScope.$on('$stateChangeStart',
function(event, next, nextParams, prev, prevParams) {
// The info of your currentUser could be obtain from a service
// or localStorage or cookies anyway you are already doing it
var authorized= checkAuthorization(next.authorazedRoles,
mySessionService.getCurrentRol());
if(!authorized) {
$rootScope.$state.go('defaultState');
// Or $rootScope.$emit('NOT_AUTHENTICATED');
// and some service will have to implement a listener for this emit
// $rootScope.$on('NOT_AUTHENTICATED', func..redirect to X State)
}
});
});

How can I dynamically set templates without messy query parameters in angular ui-router?

I'm building an artist portfolio web app where the artist can create a 'project' which consists of a series of content pieces (mostly images at this point) which can then be put in an order and the artist can choose between different preset layouts. I'm using angular and node + express. I'm struggling to find a good way to dynamically set templates. The only functional scheme i've devised so far is to put the template name in a query parameter in the url like this.
ui-sref="webapp/project/photo?template=vertical"
then in ui-router it's relatively simple to set the template using state params
templateUrl : function (stateparams) {
return 'templates/' + stateparams.template + '.html';
},
Although it's functional I don't like this mostly because it creates messy urls and allows anyone to change templates with query params or more likely load something without a real template because the url was typed incorrectly or correctly without the query parameter.
I can't make an api call from the templateUrl function because it's not injectable so I can't use the $http service. I've tried to use template provider but haven't made anything functional out of that yet. It does allow for an injectable function but that function must return an entire template instead of a url. If I can get a template url for it how can a load the template with that? I assume I'm not the first person to want dynamic templates (templates set in the database) from angular. What are my best options?
I have found a functional solution to my problem using ui-router, $stateParams, and $http. I'll be looking for a better architecture scheme as this necessitates 3 server requests every time a project is requested. One to get the template name and another to load the template file and another to load the project data. I suppose I only added one request to the norm. Anyways.. This solution is working for me but next I will be moving the logic to get template by the project name to an angular service to keep everything clean.
.state('projects/:project_url', {
url : '/projects/:project_url',
templateProvider : function ($stateParams, $http) {
return $http.get('/api/projects/' + $stateParams.project_url)
.then(function (data) {
// get template name
var templateName = data.data[0].template;
// return template by name
return $http.get('/pages/' + templateName + '.html')
.then(function (data) {
return data.data;
});
});
},
controller : 'projectCtrl'
});
http://dotjem.github.io/angular-routing/ supports your scenario with inject-able template functions. Note however that you must provide the raw template in the return statement, but that is easily done using the $template service...
It is very similar to UIRouter, so it should be a fairly easy transition if you find it worth it.
http://plnkr.co/edit/dkPIWMW236ixifETohNW?p=preview
If you take the latest stable release rather than the head you must add a "get" call to that service as: $template.get('template.html') rather than the newer: $template('template.html')

Resources