I'm working with AngularJS and am having a simple but odd issue. AngularJS is unable to locate my template file if it is in a subdirectory of a specific directory.
The below project structure is what I wish to have. I reference myFile.html by using the templateUrl property on a component templateUrl: "/MyApp/posts/myFile/myFile.html" With below structure and this import, AngularJS throws an error.
public
| javascript
| MyApp
| posts
| app.js
| index.html
| myFile
myFile.html
If I reformat my structure to the below, and change my import to templateUrl: "/MyApp/myFile/myFile.html" everything works
public
| javascript
| MyApp
| posts
| app.js
| index.html
| myFile
| myFile.html
Please don't suggest that I check the spelling, and file path. I've done that a million times and it just never works if it's in a sub directory of the posts directory
Related
My problem is simple from my point of view, but I'm struggling fixing it.
On my Hugo folder, if I resume the structure of my layouts and content folders, it's like this:
layouts
|--- _default
|--- baseof.html
|--- list.html
|--- single.html
|--- blog
|--- list.html
|--- single.html
content
|--- blog
|--- posts
The code under /layouts/blog/list.html works fine -the design of the list page under the URL on local http://localhost:1313/blog/ is as I want it to be. However the code under /layouts/blog/single.html isn't working. Instead, I got the implementation of the code of the single page under /layouts/_default/single.html.
The source of this problem might be in the fact that I migrated my blog posts from WordPress with a plugin into Hugo. And the metadata of my blog posts are like this:
---
title: ...
author: ...
type: post
date: ...
url: /2020/10/title-of-the-post/
---
And the URL of my post on local is: http://localhost:1313/2020/10/title-of-the-post/.
What I did is obviously change the url in the metadata of the post to be like this:
---
url: /blog/2020/10/title-of-the-post/
---
Thus the URL of my post on local is now: http://localhost:1313/blog/2020/10/title-of-the-post/.
However, it didn't trigger the single page under /layouts/blog/single.html -the code implemented is still the one under /layouts/_default/single.html.
I don't have more idea to try. Has someone of you figured out how I could do it ?
Here are my permalinks configuration from the config.toml as I guess some of you might ask them:
[permalinks]
post = "/:year/:month/:title/"
I ended up finding the solution: it was to delete the line type: post in the front matter of my posts (or to change it to type: blog).
I need to manage a SideMenu (http://ionicframework.com/docs/api/directive/ionSideMenus/) with multi-level hierarchy. A nice solution can be use multiple views to manage with $stateProvider.state and change the content change the content inside of <ion-side-menu>, but I do not know how to do.
Option A
|_ Sub-option 1
|_ Sub-option 2
Option B
|_ Sub-option 1
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.
I have some data in firebase that looks like this:
|
|
--users
|
--1
|
--email:"hello#gmail.com"
--name:"User 01"
--2
|
--email:"hello2#gmail.com"
--name:"User 02"
--chat
|
---JU9ZpBj7P9dWgNYN4To
|
--email:"hello#gmail.com"
--content:"Hi, i'm user 01! How are you?"
--user:"1"
--timestamp:"123456789"
---JX8ZpBnli7hliwehlfi
|
--email:"hello2#gmail.com"
--content:"Hi, i'm user 02! I'm great thanks!"
--user:"2"
--timestamp:"123456789"
I get the chat data from firebase in an object called 'messages', and my HTML/angular looks like this:
<ul class="chat" ng-repeat="message in messages | orderByPriority | reverse">
<li>
<strong>{{message.user | uid2name}}</strong> {{message.content}}
</li>
</ul>
So what I want to do is grab message.user and convert it from a userid into a name. I figured a good way would be to use a filter:
.filter('uid2name', function(loginService, $rootScope) {
// Takes a userid and outputs a users name
return function(input) {
var ref = new Firebase('https://<myapp>.firebaseio.com/users/' + input);
return $firebase(ref).name;
};
})
Now this works fine, but it does so by essentially polling firebase multiple times per second - not what I want to do at all. I have thought about caching the response in $rootScope but this seems a bit sloppy. What's the best way going about this? I am open to any ideas, I am not wed to the idea of using a filter.
Filters are one the things I love a bout Angular, but they are too heavy (since they are evaluated with every digest cycle) and definitely does't suite to your approach, unless you use cache (just don't store it in $rootScope, create a cache service instead).
Firebase is all about performance, in most cases normalization is your enemy. You already store user email, why don't you also store user name as well?
Changing the data structure to include userId in the URL of your Chat data structure may help: Data Modeling Best Practices in Firebase/AngularFire
In the end, I solved this problem by using the angular-cache plugin (the default angular cache-factory is good but it lacks a few useful features). I cached the users in order to use a filter without hammering firebase.
I'm using grunt to concatenate my .js files for my Angular app.
I've just gone through and tidied up the codebase to follow the conventions discussed here, specifically, grouping my code into small modules that represent features.
However, I'm finding that the order of concatenation appears to break the app, if a module is consumed before it is declared.
eg:
|-- src/
| |-- app/
| | |-- userProfile/
| | | | userProfile.js
| | | |-- deposits/
| | | | |-- depositFormCtrl.js
Where:
// userProfile.js
var userProfile = angular.module('userProfile',[])
// depositFormCtrl.js
angular.module('userProfile')
.controller('DepositFormCtrl', function($scope) {...});
When grunt performs the concatenation, depositFormCtrl.js appears before userProfile.js. This causes the app to throw an error, complaining:
Uncaught Error: No module: userProfile
I see lots of talk about the possibilities of using RequireJS / AMD to manage the load order of the modules. However, often it's stated that this is overkill / not required, as Angular handles this for you.
E.g: Brian Ford of the Angular team mentioned:
My personal take is that RequireJS does too much; the only feature that AngularJS's DI system is really missing is the async loading.
He's also stated elsewhere that he doesn't recommend RequireJS with Angular.
I've also seen mentioned made to using angular-loader.js, as shown on the seed project. However, as I understand it, (there's little official documentation) the loader aims to solve the problem of loading modules out of order, rather than them being referenced before used.
Adding angular-loader.js to my project didn't resolve the issue.
Is there a declaration I should be using that prevents the errors I'm having?
What is the correct way to declare modules & controllers, so that the order files are concatenated doesn't impact the code at runtime?
One technique I sometimes use is to put declarations at the start of the concatenated file. I do this by putting them in a dedicated file that will be the first one to be picked up by the concatenation utility.
//app/_declarations.js
angular.module('userProfile',[]);
//app/userProfile/userProfile.js
angular.module('userProfile')
.config(['$routeProvider', function ($router) {...});
//app/userProfile/deposits/depositFormCtrl.js
angular.module('userProfile')
.controller('DepositFormCtrl', function($scope) {...});
May not be a good fit for all scenarios, but is simple to set up and understand.
I ran into the same issue. I split the concatenation step in my GruntFile.js to two tasks, so essentially my app.js, where my Angular application is defined, is 'prepended' to the intermediate concatenated file (_app.js), and the result is saved with the same name of the intermediate file, resulting into a final '_app.js'
app.js
var TestApp = angular.module('TestApp', [...]);
Sub tasks in my concat section of my GruntFile.js
....
// Concatenate all Angular application JS files into _app.js. Note the use
// of wildcards to walk the App folder subfolders to pick up all JS files.
jsCore: {
src: [
'<%= meta.appPath%>/**/*.js',
// Do not include app.js, since it needs to be prepended to the final concat file
'!<%= meta.appPath/app.js',
// Do not include config.js, since it will need to be tokenized by RM
'!<%= meta.appPath%>/config.js'
],
dest: '<%= meta.resPath %>/_app.js'
},
// Prepend app.js to the beginning of _app.js, and save result as _app.js.
// This keeps Angular happy ...
jsApp: {
src: [
'<%= meta.appPath%>/app.js',
'<%= meta.resPath%>/_app.js'
],
dest: '<%= meta.resPath %>/_app.js'
}
...
The resultant _app.js file has the source of app.js at the beginning i.e. the declaration of TestApp.
If you split a module in multiples js files and you don't want to manage manually in which order your build should concatenate files then you will need RequireJS.
Personally, I try to avoid splitting a module in several files for several reasons :
It can be hard to find all controllers/services/etc.. from a single module
If the module is becoming too big, then it probably means you should split in several modules
It's cumbersome enough to have to declare manually a list of modules dependencies and a list of injected dependencies for each module. Add to that a list of js dependency files needed by RequireJS and you will spend most of your time declaring boring stuff instead of resolving business problems
However, if you keep the 1 module / 1 file rule, you'll see your index.html growing very quickly. Personally, I don't consider that as a big issue.
use gulp and then use gulp-angular-sort
return gulp.src('./build/src/app/**/*.js')
.pipe(sort())
.pipe(plug.concat('concat.js'))
.pipe(gulp.dest('./output/'));