I've searched everywhere for the answer but unfortunately I didn't find anything.
I have a working Angular application that looks like this:
...
<div class="container" ng-app="myApp">
<div class="page-title">
<h1>
Hello
</h1>
</div>
<div ng-view></div>
</div>
...
I'm working with ngRoute to load html partials into the ng-view div.
my JS:
var myApp = angular.module('myApp', [
'ngRoute',
'myControllers'
]);
myApp.config(['$routeProvider', '$httpProvider',
function($routeProvider, $httpProvider) {
$routeProvider.
when('/step1', {
templateUrl: 'template1.html',
controller: 'Step1Controller'
}).
when('/step2', {
templateUrl: 'template2.html',
controller: 'Step2Controller'
}).
when('/step3', {
templateUrl: 'template3.html',
controller: 'Step3Controller'
}).
otherwise({
redirectTo: '/step1'
});
}]);
Up to here, everything works as a charm. I already completed pretty much everything I needed (a multi stepped wizard).
On the last step, I needed to use <script type="text/ng-template" id="specialTemplate.html"></script> to generate some special template (a tree)
So, in my last step page partial (template3.html) I did the following:
<ul>
<li ng-repeat="item in [1,2,3]" ng-include="'specialTemplate.html'"></li>
</ul>
<script type="text/ng-template" id="specialTemplate.html">
Test
</script>
Here I got stuck. I'm getting 404 errors on console (he tries to look up specialTemplate.html in the same directory my browser's url points to), and the template does not load.
When I made some tests I saw that if the ng-include is outside of the ng-view, but inside a clean ng-controller separated from my current working flow, It does find and load the template, but this doesn't help me because I must render the tree within my working steps flow.
Is it impossible to load a <script> based template inside ng-view?
Thanks in advance for your help.
EDIT:
Version: AngularJS v1.3.0-beta.3
it could be that when you try to grab specialTemplate.html from within ngView it changes the url being pointed to by ngInclude. Try hardcoding the path to specialTemplate.html. Or you could try putting your script inside the li because it might also be a scope issue.
If you are testing in a local Windows system, then not serving up your pages from http-server might be the problem.
As a fix, install http-server globally using the commnd:
npm install -g http-server
and remember to use a sudo for Linux system.
Once the server installed, start the server using the command:
http-server
Now, go to http://127.0.0.1:8080/ in your browser and navigate to your desired page.
Related
I worked on a little startpage for my browser. Now I would like to make some changes to it, so it updates the index.html file depending on a text file, when this got changed. What whould be an efficiant way to solve this problem?
My approach would be to create a text file and read line by line from it and update the html file. In the text file I would store the links shown on my startpage - I thought maybe something like this:
|cat_media
https://mailbox.org,mail
https://netflix.com,netflix
...
http://crunchyroll.com,crunchy
https://jott-uh-be.bandcamp.com,bc
|cat_social
https://pr0gramm.com,pr0
https://stackoverflow.com,stackoverflow
https://twitter.com,twitter
https://instagram.com,insta
When the line starts with the symbol |, it creates a new <div> with the class category and the string in that line (e.G. class= 'category cat_media'). Otherwise, if the line starts with http, it will add a href-link (e.G. <a href='https://mailbox.org'>mail</a>) to the html-code.
I got this website hosted on my raspberry pi with nginx and uploaded it to my github pages.
You don't have to update the index.html file.
You can create dynamic content.
You can use PHP:
You can learn it here:
https://www.w3schools.com/php/default.asp
And here is how to read a file
http://php.net/manual/en/function.fread.php
Or if you cant use PHP you can use Javascript:
<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<script>
$(() => {
$.ajax({
url:'your-config-file.xt',
success: function (data){
console.log(data); //this is the config file. just for loop it and modify the dom
}
});
});
</script>
But your config file must contains the string how the links should be shown.
For example:
|catergory one
yt: https://www.youtube.com
In my Angular 4 app, I am using innerHTML to show description of the exercises which are in HTML format.
<li *ngFor="let exercise of exercises">
<div [innerHTML]="exercise.longDescription"></div>
</li>
These descriptions can also contain images
<img src="/file/na\6ad7k4ynon6yh2qcibcdqxwcey.jpg">
and that is where I am struggling because I need to set the base href for these images to localhost:8080 where my backend is. Angular is trying to get them from standard localhost:4200 (ng serve) so I am getting errors.
Any idea how to do that?
Found a solution, not sure if is the cleanest one but it gets the job done.
I created a function in my exercise model that adds environment.URL to the src (which is localhost:8080 for development and server's API for production).
public getHTML () {
return this.longDescription.replace(/<img src="([^"]+)">/, '<img src="'+environment.URL+'$1">');
}
and I access it like this
<div [innerHTML]="exercise.getHTML()"></div>
instead.
Environment const looks like this:
export const environment = {
production: false,
URL: 'http://localhost:8080'
};
There are similar questions like mine, but they couldn't help me out.
html:
<!DOCTYPE html>
<html>
<head>
<title>Test-Site</title>
<script src="scripts/angular.js"></script>
<script src="scripts/angular-route.js"></script>
<script src="~/App_Data/mainApp.js"></script>
<script src="~/Controllers/testController.js"></script>
</head>
<body>
<div ng-app="~/App_Data/mainApp" ng- controller="~/Controllers/testController">
Write your Name:<input type="text" ng-model="name.firstName" />
Your Name: {{name.firstName}}
</div>
main.app.js:
var mainApp = angular.module("mainApp", []);
test.controller.js:
mainApp.controller("testController", function ($scope) {
$scope.name = { firstName: "Peter" };
});
Chrome console gives me following errors:
Test.html:8 GET http://localhost:55835/~/Controllers/testController.js
Test.html:7 GET http://localhost:55835/~/App_Data/mainApp.js
angular.js:63 Uncaught Error: [$injector:modulerr] Failed to instantiate module ~/App_Data/mainApp due to:
Error: [$injector:nomod] Module '~/App_Data/mainApp' is not available! You either misspelled the module name or forgot to load it. If registering a module ensure that you specify the dependencies as the second argument.
Everything was fine, until I moved the js-files into their folders.
What am I doing wrong?
You are using the server side path ~/ in a client side page. You cannot use the server side path in this way. You need to provide the full path from the root of the site to your files; most likely, just removing the ~/ will be enough.
As a side note, normally the App_Data folder is for things like Database files and other server resources; it seems an odd place to put your mainApp.js file.
I have working code that I want to demo with JsBin but I can't get the AngularJS directive templateUrl to work (it does work with the template value).
http://jsbin.com/guvok/ is trying to reference http://jsbin.com/razit/ but fails.
For the sake of completeness and posterity here's the code:
hello.html
<!DOCTYPE html>
<html ng-app="hello">
<head>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.19/angular.min.js"></script>
</head>
<body>
<div hello></div>
</body>
</html>
hello.css
.hello__content {
background: #fff;
}
hello.js
var meter = angular.module('hello', [])
.directive( 'hello', function() {
return {
restrict: 'A',
replace: true,
//template: '<p class="hello__content">hello</p>',
templateUrl: 'http://jsbin.com/razit/',
};
});
template.html
<p>hello, world</p>
When I run http://jsbin.com/guvok/, I get the following error in the Javascript console in my browser:
Error: [$sce:insecurl] http://errors.angularjs.org/1.2.19/$sce/insecurl?p0=http%3A%2F%2Fjsbin.com%2Frazit%2F
If you look up "$sce:insecurl", you'll find the AngularJs error reference doc that says,
AngularJS' Strict Contextual Escaping (SCE) mode (enabled by default)
has blocked loading a resource from an insecure URL.
Typically, this would occur if you're attempting to load an Angular
template from an untrusted source. It's also possible that a custom
directive threw this error for a similar reason.
It also offers a few ways to solve the problem, which is essentially a CORS issue.
Put this at the top of your HTML (after the script tag that loads Angular):
<script type="text/ng-template" id="templateURL">
<!-- TEMPLATE MARKUP GOES HERE -->
</script>
Edit: In your case, the ID would be "http://jsbin.com/razit/", that way you wont have to edit your directive. Worst case, change the templateURL to not reference an external jsBin.
Edit #2: Changing the templateUrl to a string value not referencing an external url or with the http protocol, I now see your output in jsBin edit mode.
jsBin here: http://jsbin.com/dutofete/1/
I first initialize my app with ng-app="myApp" in the body tag and this works fine for all angularized-html that is loaded on first page load.
Later on I have some code that loads angularized-html in to the DOM.
In angular 1.08 I could just run angular.bootstrap($newLoadHTML, ["myApp"]) after the load and it would work; where $newLoadHTML is the newly added HTML grabbed with jQuery.
In angular 1.2 this does no longer work:(
Error: [ng:btstrpd] App Already Bootstrapped with this Element '' http://errors.angularjs.org/1.2.0-rc.2/ng/btstrpd?p0=%3Cdiv%20ng-controller%3D%22AfterCtrl%22%3E
I am getting this error which I understand, but I don't know how to solve it.
What I need to be able to do is load angularized-html and then make angular aware of it.
Here is a plunker to illustrate it: http://plnkr.co/edit/AHMkqEO4T6LxJvjuiMeT?p=preview
I will echo what others have mentioned: this kind of thing is generally a bad idea, but I also understand that you sometimes have to work with legacy code in ways you'd prefer not to. All that said, you can turn HTML loaded from outside Angular into Angular-bound views with the $compile service. Here's how you might rewrite your current example to make it work with $compile:
// We have to set up controllers ahead of time.
myApp.controller('AfterCtrl', function($scope) {
$scope.loaded = 'Is now loaded';
});
//loads html and afterwards creates a controller
$('button').on('click', function() {
$.get('ajax.html', function(data) {
// Get the $compile service from the app's injector
var injector = $('[ng-app]').injector();
var $compile = injector.get('$compile');
// Compile the HTML into a linking function...
var linkFn = $compile(data);
// ...and link it to the scope we're interested in.
// Here we'll use the $rootScope.
var $rootScope = injector.get('$rootScope');
var elem = linkFn($rootScope);
$('.content').append(elem);
// Now that the content has been compiled, linked,
// and added to the DOM, we must trigger a digest cycle
// on the scope we used in order to update bindings.
$rootScope.$digest();
}, 'html');
});
Here is an example: http://plnkr.co/edit/mfuyRJFfA2CjIQBW4ikB?p=preview
It simplifies things a bit if you can build your functionality as a directive instead of using raw jQuery--you can inject the $compile and $rootScope services into it, or even use the local scope inside the directive. Even better if you can use dynamic binding into an <ng-include> element instead.
Your approach doesn't seem right. You are usinging jQuery and Angular together in an inappropriate way that is likely to have conflicts.
Angular's built in template support is the best way to do this either using ng-include or you can use Angular's routing and along with ng-view. The documentation is here:
http://docs.angularjs.org/api/ng.directive:ngInclude
http://docs.angularjs.org/api/ngRoute.directive:ngView
The simplest possible thing would be to just set the ng-include to the url string:
<div ng-include="'ajax.html'"></div>
If you actually need it to load dynamically when you do something then this is a more complete solution for you:
http://plnkr.co/edit/a9DVEQArS4yzirEQAK8c?p=preview
HTML:
<div ng-controller="InitCtrl">
<p>{{ started }}</p>
<button ng-click="loadTemplate()">Load</button>
<div class="content" ng-include="template"></div>
</div>
Javascript:
var myApp = angular.module('myApp', [])
.controller('InitCtrl', function($scope)
{
$scope.started = 'App is started';
$scope.loadTemplate = function() {
console.log('loading');
$scope.template = "ajax.html";
}
}).controller('AfterCtrl', function($scope)
{
$scope.loaded = 'Is now loaded';
});
Loading an AngularJS controller dynamically
The answer to this question fixed my problem. Since I need to create the controllers after the content was added to the DOM. This fix requires me too register controllers after I have declared it. If someone has an easier solution pleace chip in.
One other gotcha that leads to this Bootstrapping error is the nginclude or ngview scenarios where your dynamic html includes script references to angular js.
My html below was causing this issue when it got injected into an existing Angular page. The reference to the angular.min.js caused Angular to rebootstrap:
<div id="fuelux-wizard" class="row-fluid" data-target="#step-container">
<ul class="wizard-steps">
<li data-target="#step1">
<span class="step">1</span>
<span class="title">Submit</span>
</li>
<li data-target="#step2">
<span class="step">2</span>
<span class="title">Approve</span>
</li>
<li data-target="#step3">
<span class="step">3</span>
<span class="title">Complete</span>
</li>
</ul>
</div>
<script src="/Scripts/Angular/angular.min.js"></script>
<script type="text/javascript">
angular.element('#requestMaster').scope().styleDisplayURL();
</script>