Angular 4: Setting img src base href inside of innerHTML - html

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'
};

Related

how to display images from nestjs server to Angular

When I upload a product from Angular side, It Post the product with imagepath, and the image is getting stored in the NestJs folder also, but I can not display product with it's image. The product is displaying at frontend but without it's image that is referenced and saved at the backend.
Anguar FrontEnd Code .ts
export class BooksComponent implements OnInit {
BookForm = new FormGroup({
_id: new FormControl(''),
name: new FormControl(''),
author: new FormControl(''),
price: new FormControl(''),
genres_name: new FormControl(''),
coverimage: new FormControl(''),
});
results?: Book[] = [];
searchedText: string = '';
constructor(
private readonly apiService: ApiService,
private router: Router
) {}
ngOnInit() {
this.apiService.getallbooks().subscribe((data) => {
this.results = data;
console.log(this.results);
});
}
Frontend html code.I'm getting all the information but not the image, here I'm providing src in img tag to display images
<div class="grid" *ngFor="let result of results">
<div class="blog-card spring-fever" style="padding: 0.5rem; z-index: 100">
<img
class="image"
src="http://localhost:3000/{{ result.coverimage }}"
alt=""
height="400px"
width="250px"
style="border: 1px solid red"
/>
This is the information of the Product that is coming from the backend
And when I try like this src="{{result.coverimage}}" or [src]="result.coverimage" I got error localhost:4200/assets/imagename not found(404). well that is obvoius!. because there is not such path, 4200 is for Angular. but I'm uploading the images at the backend assets folder which is located at localhost:3000/assets/, and we always upload files to backend for dynamic approach from database
In your highlighted part of your post you ask how to display the image, i.e you suspect the problem is in the frontend. However there is a missing part from the provided context. In the line where the html magic happens (The img tag src attribute).
There you are string interpolating a property called coverimage under the results object. We do not see what is inside the coverimage from your backend response in the frontend screenshot. If it is an id of a document then it will not be parsed correctly. The src attribute accepts:
APNG, AVIF, GIF, JPEG, PNG, SVG, and WebP. Or base64 (which seems not the case here).
When you have the image with one of the acceptable supported formats as stated in MDN correct you can map the property to the src attribute either via
1- string interpolation:
<img src="{{imagePath}}" />
2- property binding:
<img [src]="imagePath" />
The second way is more popular, but both work fine.
PS: it is a best practice and accessibility recommended to populate the alt="" property
If you are struggling to display the images coming from server, like I was, or you are struggling with the data that is coming NestJs. Then this might work for you as it worked for me.
So in my case I had a list of books and each book has path for its image. I was using ngFor and set the image src with the path. That is the right way. But the images were not visible and Network was showing images as text/html type. The actual issue here was not the type,the actual issue was in my URL.I had a folder in NestJs server by the name of assets,that is preset at root, and I had set the path for the images(in NestJs file upload code), like this ./assets/. That is also the correct way to set the destination folder.I was able to see the images at browser like this http://localhost:3000/imagename.png,and that means my server configured to server/serve my images over root URL that's why I can access them http://localhost:3000/imagename.png. But my api was returning images in a format that contains ./assets/ in the URL.
So with the following code
<div *ngIf="result.coverimage">
<img
class="image"
src="http://localhost:3000/{{ result.coverimage }}"
alt=""
height="400px"
width="250px"
style="border: 1px solid red"
/>
</div>
I am assuming that I'm hitting the Url like this http:localhost:3000/imagename.png. But actually Angular was seeing the URL like this http:localhost:3000/./assets/imagename.png. And this is note the correct URL Format. Urls don't work with . or ,.Also becasue my server is configured at root, this urlhttp;//localhost:3000/assets/imagename.png is also wrong.And root means that, whatever the thing is set at root, that is directly access able after your server's port number. Example http://localhost:YourServerPortNumber/TheThing_Set_at_Root.
So the solution for this issue is the following
src="http://localhost:3000/{{
result.coverimage.replace('./assets/', '')
}}"
With above .replace('./assets/', '') we are removing the ./assets/ and repalcing it with '' empty space. So now URL is in this formathttp://localhost:3000/imagename.png.

Display Images on HTML using MongoDB, But it didn't show

I have the code backend using Node.js and Front end in HTML. I tried to get the image stored in mongo to front end. But in HTML it doesn't shows the image. But when I paste the binary data of image in img src tag it works. Help plz.
index.js
function loadImages() {
let isbn=''
let imgSource=''
if (CURRENT_URL.includes('#')) {
isbn = CURRENT_URL.substr(CURRENT_URL.indexOf('#') + 1,
CURRENT_URL.length);
console.log(isbn);
}
axios.get(baseUrlLocal + '/book/image/'+isbn)
.then(response => {
console.log(response.data)
document.getElementById('imgSource')
.setAttribute(
'src', 'data:image/png;base64,' +
btoa(unescape(encodeURIComponent(response.data))) +"'"
);
})
.catch(err => {
console.log(err);
});
}
HTML
<div class="card-body" id="image-src">
<img id="imgSource" src="" alt="Red dot" />
</div>
I don't think you can do this in node.js
document.getElementById('imgSource')
.setAttribute(
'src', 'data:image/png;base64,' +
btoa(unescape(encodeURIComponent(response.data))) +"'"
);
document object is available in your browser mate. In node js you can't just use this like that. If you want to render the image you have processed, then you might want to look for a front end template engine
like
ejs
pug
handlebars
since ejs's syntax is a little bit annoying and can be very confusing sometimes you can use an alternative like handlebars take a look at here
handle bars is like a template engine. If you are familiar with Laravel or ASP.NET's Razor blade or Angular's string interpolation techniques this is very much like that so
go to your shell and install handlebars like this
npm install --save handlebars
since this is a little too much of a topic to discuss as an answer I'll just provide you with this link a tutorial on how to install and use handle bars. try that mate you will be able to achieve what you are looking for.. Cheers ...

Is it possible to allow user to edit and save html template in angularjs application

I have an traditional asp.net application which reads HTML template and renders it inside div control. Using bootstrap xeditable user can edit certain parts of the template (only text). This template is later used to send emails. This functionality is working fine. Now I am rewriting this application using AngularJs and WebApi. I am using angular route to route to different pages (plain html) of the application. I am able to load the template using directive. now I want to allow user to edit the text and save the complete template so that it can be used later for sending email.
MyTemplate.html
<p>this is some text</p>
<p>this is some more text</p>
<p>this is some another text</p>
Directive
myapp.directive("customDirective", function () {
return {
templateUrl: 'MyTemplate.html'
};
});
Notify.html
<div>
<h2>{{message}}</h2>
<input type="button" ng-click="Redirect()" value="Report" />
</div>
<custom-directive></custom-directive>
I want that user should be able to edit the text in MyTemplate.html and save it as complete template for later use. Is this achievable?
Do not store it in file. Store the template in your database. Provide a default value there, so something shows if the user has not modified it yet.
In you directive, load the template from your database through your API. After you do that, append the template to the contents of your directive inside your link callback function and compile the directive (if needed).
myapp.directive("customDirective", ($compile, yourService) => {
return {
link: (scope, elem) => {
yourService.fetchTemplate().then(template => {
elem.html(template);
$compile(elem.contents())(scope);
});
}
}
});
Please make sure to sanitise your data properly. It could be fairly dangerous injecting and compiling template created by the user.
I hope this points you in the right direction.
Edit
You might not event need the $compile step. It depends on what kind of template you have in mind. If it is just a simple element without any connection to angular, simply skip the $compile line.
Edit 2 - Display the template on click
Please note the following is just a very simplified version, but it should point you in the right direction.
In your parent controller
$scope.state = {
displayTemplate: false
};
In your template
<my-template-directive ng-if="state.displayTemplate"></my-template-directive>
<button ng-click="state.displayTemplate = true">Show Template</button>

Angular bootstrapping after load of html

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>

EmberJS set active class for dynamic linkTo on menu when direct accessed

i've been trying this since last week, to make the active class work on those dynamic links:
<li>{{#linkTo tag 'bw'}}Black and White{{/linkTo}}</li>
<li>{{#linkTo tag 'instax'}}Instax{{/linkTo}}</li>
<li>{{#linkTo tag 'digital'}}Digital{{/linkTo}}</li>
I put a code running here: http://jsbin.com/opuzop/1/edit so if you feel ok to help me with that would be great :D it's my photo portfolio as well.
Also, if I try to upload to the newer version of Ember, some stuff stop to work, like the JS I created on
App.GeneralView = Ember.View.extend({
didInsertElement: function() {
if(this.$() !== undefined){...
It was created to load after the view render, so I do a image resize and a body resize too, and set everything horizontal, but with the newer version it only work when accessed directly.
Also, sometimes it don't get the JSON from Tumblr and stop working.
I'm not sure, but I think it has to do with the serialization of your object, try adding something like this in your "App.TagRoute" route:
serialize: function(param) {
return {tag: param.tag}
}