Add ng-if to an image in html - html

So, I have two images on a html page in my ionic project, and I want the second image to show up when the first one is clicked.
Therefore i added a onClick to my image like:
<img src="path"
alt="foo"
style="foo;
width:foo;
left:30%;top:30%"
class = "foo"
onclick="ng-model='bar'" >
And the second image
<img src="path"
*ngIf="bar">
But it is not working that way. Is it the wrong way? I tried it that way to avoid additional javascript.

You can accomplish this as follows:
<img src="http://via.placeholder.com/350x150/222222" (click)="hiddenImage.style.display='inline'"/>
<img #hiddenImage style="display: none" src="http://via.placeholder.com/350x150/888888"/>
But it may still be a better idea to do it differently depending on what your exact use case is.
Using *ngIf you would probably still need a variable that holds the value of whether the image should be shown or not in your template:
<img src="http://via.placeholder.com/350x150/222222" (click)="showImage=true"/>
<img src="http://via.placeholder.com/350x150/888888" *ngIf="showImage"/>
In your Component you should declare:
showImage: boolean = false;

Related

Placeholder for div background image in Angular 4

item.imgSrc has a URL which takes time to load on screen. Is there any way to add a placeholder image or default image until the item.imgSrc image is fully loaded?
<div class="style" *ngFor="let item of array;
<div [style.backgroundImage]="url('+ item.imgSrc +')" class="image"></div>
</div>
You can use [ngStyle]="{'background-image':'url(' +imageUrl+ ')'}"
One way, You can create a directive to set a placeholder image for an element in html.
in your case, you can do as below also :
<div>
<img src="img/placeholderDefault.jpg" ng-src="{{item.imgSrc}} " height="150px " width="300px ">
</div>
where when your real image is loaded then it will replace the placeholderDefault image. and you can set the ng-src image base on your need in your desired scope.
If ng-src does not work in angular 2+ then, try
<img src="{{item.imgSrc}}">
or
<img [src]="item.imgSrc">
in this case, declare an object in your scope in the controller as
$scope.item={} and set $scope.item.imgSrc="defaultImagePath" and when your new
original image loads then replace with the original image path.
Hope this idea can help you

How to disable image tag when image is not loaded or API returned path is not valid in Angular4

I am working in an Angular Application,In this application I am using images.Image path is getting from database through API .
When a user clicked on a product the product name is passed to the API and the Images related to the product is get as response .In my application I have maximum of five images for a specific product.
If I hover on the images it will display the big size image of it.
My HTML
<div class="row">
<img id="sm001" (mouseenter)="mouseEnter($event)" src="{{smallImages['0']['small_Images']}}" alt="img1" class="img-thumbnail" [attr.ref]="bigImages['0']['big_Images']">
<img id="sm005" (mouseenter)="mouseEnter($event)" src="{{smallImages['1']['small_Images']}}" alt="img2" class="img-thumbnail" [attr.ref]="bigImages['1']['big_Images']">
<img id="sm002" (mouseenter)="mouseEnter($event)" src="{{smallImages['2']['small_Images']}}" alt="img3" class="img-thumbnail" [attr.ref]="bigImages['2']['big_Images']">
<img id="sm003" (mouseenter)="mouseEnter($event)" src="{{smallImages['3']['small_Images']}}" alt="img4" class="img-thumbnail" [attr.ref]="bigImages['3']['big_Images']">
<img id="sm004" (mouseenter)="mouseEnter($event)" src="{{smallImages['4']['small_Images']}}" alt="img5" class="img-thumbnail" [attr.ref]="bigImages['4']['big_Images']">
</div>
What I want to do is ...
1, If the API returns only 3 images(max is 5) ,I want to hide the remaining 2 img tags (I don't want to show any alt tag contents just want totally disable the img tag).
2,if the API returned image path is not(not present in assets folder )loaded in img tag ,I want to disable that img tag.(empty or null or " " or undefined).
is it possible please guide me to solve this . Thanks
In regards to issue 1:
<div *ngFor="let image of smallImages">
<img [src]="image.small_Images" (mouseenter)="...">
</div>
The ngFor gives you access to the let <value> within that. This makes it automatically add the amount of images as are available in the array.
In regards to issue 2:
This is a little bit more difficult because this means you will have to preload the images.
You can lookup some ways to do this but I think you're talking two very different issues here, so normally you would turn it into two different questions.
In regards to an easy (JavaScript in TypeScript) way of preloading images:
const img = new Image();
img.onload = () => {
console.log('Images is loaded and exists!');
}
img.onerror = () => {
console.log('Image could not be loaded for whatever reason.');
}
img.src = 'blabla'
Of course you will need to figure out how to run this code on your results. So you're talking a big difference between component logic and template logic; therefore: This should be a different issue and a different StackOverflow question.
Rather than controlling the image display purely in HTML, you should be using "ngFor" to loop through the set of images returned by a query against your API, something like this:
<div class="row">
<ng-template *ngFor="let image of images">
<img id="{{image.id}}" (mouseenter)="mouseEnter($event)" src="{{image.url_small}}" alt="{{image.alt}}" class="img-thumbnail" [attr.ref]="{{image.url_big}}">
</ng-template>
</div>
You would then construct the images array as a property of your controller in your Typescript code when you process the results of the API that returns you the image data.
The "Tour of Heroes" covers this on their page about displaying data, here.
I could provide a more focused answer if you provided more details of the API you're making your requests against, and the actual code that is making those requests, but hopefully you can take it from here.

Repeated content (sub-template) in AngularJS

I have a template which contains (in part) exactly the same content repeated two or three times with minor changes to the bindings, eg:
<div class="xyz-state0" data-ng-hide="data.error || !data.states[0].name">
<div class="xyz-content">
<img data-ng-src="{{data.states[0].image}}" width="48" height="48">
<span>{{data.states[0].name}}</span>
</div>
</div>
<div class="xyz-state1" data-ng-hide="data.error || !data.states[1].name">
<div class="xyz-content">
<img data-ng-src="{{data.states[1].image}}" width="48" height="48">
<span>{{data.states[1].name}}</span>
</div>
</div>
How do I write this to avoid duplicating this HTML? This is specific to its parent view (it won't be used anywhere else) so creating a full-blown widget seems wrong.
Basically I want something similar to ngRepeat, but I can't use that for the following reasons:
I need a specific (and different) style on each parent div.
I need to render a specific number of divs (2 in this case, 3 in another) regardless of whether or not they exist in the scope (ie. data.states could only have 1 element in it, but it still needs to create both divs).
In the other case the items need to be rendered out of order (first 1, then 0, then 2).
I've managed to get a template fragment in a separate HTML file and included it with ngInclude, but I don't know how to get a single name in its new scope to refer to a specific item. My first attempt was this, which doesn't work:
<div class="xyz-state0" data-ng-include="'state.tpl.html'" data-ng-init="state=data.state[0]"></div>
<div class="xyz-state1" data-ng-include="'state.tpl.html'" data-ng-init="state=data.state[1]"></div>
I suspect I could probably do it with a custom controller, but that seems like a heavy solution too. What's the Right Way™?
This is pretty much a textbook case for a custom directive. Define a directive, and then you can do
<state ng-repeat="item in data.states" item="item">.
Alternatively, if a custom directive is too much overkill (depends on whether you'll be reusing that view component elsewhere, mainly), you could just put an ng-repeat on the entire div. The only real issue is the class="xyz-stateN" stuff, but I bet you could hoke that up with ng-class usage.
EDIT:
if you do an ng-repeat, you can just use the $index key (as long as you're always counting up from zero and the state class is the same as the index). Something like
<div ng-class="{{'xyz-state'+$index}}" ng-repeat="state in data.states" data-ng-hide="data.error || !state.name">
<div class="xyz-content">
<img data-ng-src="{{state.image}}" width="48" height="48">
<span>{{state.name}}</span>
</div>
</div>
Would probably work fine. All that said, it's almost always worth making a directive in my opinion. Code gets recycled all the time, plus you can be cautious with namespacing and modularizing if that makes you nervous.
Well, this seems to do the trick (thanks to pfooti for the hint). I'm still not entirely happy with it as the directive is registered globally, whereas I really only want it in this one place.
state.tpl.html:
<div class="xyz-content" data-ng-show="state.name">
<img data-ng-src="{{state.image}}" width="48" height="48" />
<span>{{state.name}}</span>
</div>
view.tpl.html:
<div data-xyz-state="data.states[0]" class="xyz-state0"
data-ng-hide="data.error"></div>
<div data-xyz-state="data.states[1]" class="xyz-state1"
data-ng-hide="data.error"></div>
app.js:
app.directive('xyzState', [function() {
return {
templateUrl: 'state.tpl.html',
scope: {
state: '=xyzState',
},
};
}]);
Interestingly it doesn't work if I try to declare the introducing element as <xyz-state ...> instead of <div data-xyz-state="" ...>, despite the docs saying that this ought to work too. I assume there's some sort of validation thing interfering here.
Just as an FYI, I later revisited this code and decided to do it like this instead: (I'm letting my original answer stand as that is more like what I was originally asking for, and they both seem reasonable in different cases.)
view.tpl.html
<div data-ng-repeat="state in data.states" data-ng-if="!data.error"
data-ng-class="state.class">
<div class="xyz-content" data-ng-show="state.name">
<img data-ng-src="{{state.image}}" width="48" height="48" />
<span>{{state.name}}</span>
</div>
</div>
app.js
...
while ($scope.data.states.length < 2)
$scope.data.states.push({});
$scope.data.states[0].class = 'xyz-state1';
$scope.data.states[1].class = 'xyz-state2';
...
I've done something similar for the other (3-item) case, except there as I wanted to rearrange the order of the items I added an order property for the desired order in the controller and then used data-ng-repeat="button in data.buttons|orderBy:'order'" in the view.
This does mean that a bit of view definitions (display order and CSS classes) have leaked into the controller, but I think the benefit to code clarity outweighs that.

How to transform apex static resource url (image) code to html?

I have the data url of my image in the static resource library, but I want to change it in html form so that I can customize it's class from css. I don't want to edit my css.
Here is my apex static resource url code:
<apex:image id="theImage" value="{!$Resource.mikee}" width="140" height="140"/>
Also, i just copied this code from a certain site, so I'm really not sure how the 'id' works. I mean it says that it's a generated id.
Anyway, I want it to be like this:
<img class="img img-circle img-responsive" id="mikee" data-src="[mikee]/mikee.jpg"/>
I'm using bootstrap to make a circular cut on my image.. However, it's not working, what seems to be the problem?
Have a look at the apex:image documentation.
To set the class in the resulting HTML you need to set the styleClass attribute. E.g.
<apex:image id="theImage" value="{!$Resource.mikee}" width="140" height="140" styleClass="img img-circle img-responsive"/>
If you want to set the HTML data-src attribute you can use the Salesforce pass-through attributes. E.g.
<apex:image id="theImage" html-data-src="[mikee]/mikee.jpg" width="140" height="140" styleClass="img img-circle img-responsive"/>
Note that the {!$Resource.mikee} Visualforce notation is going to give you a URI to the Resource image. It isn't intended to read the content of the resource as a string path. You might be better off with a custom setting and then using {!Setup.MyCustomSetting__c.Url__c}
Finally, there is a dedicated salesforce.stackexchange.com site that is a great place for asking Salesforce specific questions.

How to load bootstrap thumbnail images

I've started using Bootstrap for a project, and in particular, the Thumbnails component. On the thumbnails example on the documentation, the following sample code is shown:
<ul class="thumbnails">
<li class="span4">
<a href="#" class="thumbnail">
<img data-src="holder.js/300x200" alt="">
</a>
</li>
...
</ul>
Notice the use of data-src to replace the usual src attribute on the <img> tag.
I assumed that to get my thumbnails working, I should use data-src instead of src for the images, but that does not seem to be the case. I've only been able to load images by defining the src attribute. It seems others are having the same problem.
Is this a typo in the documentation, or did I not understand correctly how to use data-src?
I believe that the only reason of why bootstrap guys are using data-src instead src, it's because of holder.js. You should use src instead of data-src because data-src is only used for the javascript library that generates the example images of a certain size, and src is the normal attribute for specifying the location of an image (Source: W3C)
Why are they using in the documentation data-src? I suppose that even the syntax <img src="holder.js/100x200"></img> is accepted by the library as it is in the holder.js documentation, when we access to the page it throws a 404 error in the image even when the image is displaying, because there is not any file in the specified path, what it's weird.
Why do they put that in the documentation code? I really don't know. Probably it's a mistake. But I am sure that you should use src instead data-src in thumbnails.
How to use it
Include holder.js in your HTML:
<script src="holder.js"></script>
Holder will then process all images with a specific src attribute, like this one:
<img src="holder.js/200x300">
The above tag will render as a placeholder 200 pixels wide and 300 pixels tall.
To avoid console 404 errors, you can use data-src instead of src.
Holder also includes support for themes, to help placeholders blend in with your layout. There are 6 default themes: sky, vine, lava, gray, industrial, and social. You can use them like this:
<img src="holder.js/200x300/industrial">
Bootstrap uses Holder for thumbnails in its documentation.
It's pretty well explained on the Holder github page.
Include holder.js in your HTML. Holder will then process all images with a specific src attribute... The tag will render as a placeholder. To avoid console 404 errors, you can use data-src instead of src.
In order for me to get this to work, I had to call the run() function in holder.
I am using require to load backbone views, inside my view I include holder
var Holder = require('holderjs');
Then inside render I can run
Holder.run();
And in my template I have
<div class="row">
<div class="col-sm-6 col-md-4">
<div class="thumbnail">
<img data-src="holder.js/200x200/text:hello world">
<div class="caption">
<h3>Thumbnail label</h3>
<p>...</p>
<p>Button Button</p>
</div>
</div>
Hope that helps.
I couldn't figure it out either, as far as I understand it holder.js is actually a completely separate js file to act as an img placeholder from http://imsky.github.io/holder/
data-src is used to pass to the javascript, the /100x200 is the dimension of the picture you want the javascript 'holder.js' to take up for the real img.
I think the idea is to prototype using this (data-src="holder.js/300x200") and then replace it with sized pictures (src="Logo.png") afterwards.
For future Googlers looking for how to use with NPM/build jobs this worked in my case:
window.Holder = require('holderjs').default;