How to display image url in vue.js - vue.js

So This is correct way to display image in vue
<img class="cur-img" src="~#/assets/img/test.png" alt="temp-img">
However, the following way is incorrect, if templateImg is a string represent by "~#/assets/img/test.png"
<div v-for="(item,index) in items" :key="index">
<img :src="item.templateImg" alt="template-img">
</div>
Is there any way to fix it?

Usually, you will want to import the asset in your JS code. For example:
<template>
<img :src="image" />
</template>
<script>
import testImage from "#/assets/img/test.png"
export default {
image: testImage
}
</script>

Use the following:
<img :src="require(item.templateImg)">
When we are binding src to a variable, it is giving its raw value to the img tag, which means it's expecting a full resource URL. It's up to us to provide a complete data URL to that resource, which means creating a corresponding absolute resource URL out of the relative asset path that we're using.
Thus, we need to fetch it using require(). If you are using an absolute path like a base64 data image URL, or compete image URLs, then in such cases you don't need require(), and your current code will work just fine.

Related

Odoo employee image is not been showed on website template

I'm trying to show the employee's picture (fields: hr_employee.image) on a website template. But the template just show the default picture for employees instead of the loaded image.
I tried this:
<span t-field="employee.image" t-options="{'widget': 'image', 'style': 'height:200px;width:200px;'}"/>
And also, tried this:
<div t-field="employee.image" t-options="{'widget': 'image', 'style': 'height:200px;width:200px;'}"/>
And this:
<img t-field="employee.image" t-options="{'widget': 'image', 'style': 'height:200px;width:200px;'}"/>
Template just show this:
I'm afraid accessing images isn't as simple as that since you need sudo access to get them. If you're accessing the built-in employee module then the base model already provides this sudo access for you. Instead use the following:
<img t-att-src="image_data_uri(employee.image_1920)" style="max-height:85pt;max-width:90%"/>
The 1920 refers to the image's size. You can also use employee.image_1024, employee.image_512, employee.image_256 or employee.image_128
If you're trying to access images from your own custom module then you'll need to update the .py file to access the image and provide its public url.
You can use website.image_url to define the image src attribute.
<img t-att-src="website.image_url(employee, 'image_medium')" class="img shadow rounded" alt="Employee"/>
The above code is taken from website_hr
module (aboutus template)

DebugElement.query does not work with elements added dynamically to the dom in a spec

I have an app that is using ngx-bootstrap to show a tooltip on mouseover. I want to test that the content, which is dynamically added, shows properly. In order to do this I have a test that looks like this:
it(shows the right tooltip', fakeAsync(() => {
fixture.debugElement.query(By.directive(TooltipDirective))
.triggerEventHandler('mouseover', null);
tick();
fixture.detectChanges();
expect(fixture.debugElement.query(By.css('.tooltip-inner')).nativeElement)
.toBe('the tooltip text');
}
This results in an error that indicates that fixture.debugElement.query(By.css('.tooltip-inner')): "Cannot read property 'nativeElement' of null"
If I print out the content of fixture.debugElement.nativeElement I get this:
<div id="root1" ng-version="5.2.9">
<my-component>
<div ng-reflect-tooltip="the tooltip text">
<img src="images/test.png">
</div>
<bs-tooltip-container role="tooltip" class="tooltip in tooltip-right">
<div class="tooltip-arrow arrow"></div>
<div class="tooltip-inner">the tooltip text</div>
</bs-tooltip-container>
<my-component>
</div>
The important take away is that the html exists - it is just not accessible by the DebugElement.query.
My current solution to get the spec passing is to change the expect to:
expect(fixture.debugElement.nativeElement.textContent.trim())
.toBe('the tooltip text');
This works, but it is a hack that will fall to pieces if I run into a similar situation with multiple tooltips (for example). Has anyone been able to handle this in a better way? Am I not setting this spec up correctly?

Change element type at runtime

Is it possible to dynamically define the type of an element inside a custom components template at runtime?
I'd like to avoid duplication of the inner contents of the button and a element in the following example:
<template>
<button if.bind="!isLinkBtn">
<span class="btn-icon">${icon}</span>
<span class="btn-text">${contentText}</span>
</button>
<a if.bind="isLinkBtn">
<!--
The content is a 1:1 duplicate of the button above which should be prevented
somehow in order to keep the view DRY
-->
<span class="btn-icon">${icon}</span>
<span class="btn-text">${contentText}</span>
</a>
</template>
Is it possible to write something like this:
<template>
<!--
The type of element should be defined at runtime and can be a standard HTML "button"
or an anchor "a"
-->
<element type.bind="${isLinkBtn ? 'a' : 'button'}">
<span class="btn-icon">${icon}</span>
<span class="btn-text">${contentText}</span>
</element>
</template>
I'm aware of dynamic composition with <compose view="${widget.type}-view.html"></compose> but as far as I know, this won't allow me to create default HTML elements but only custom components, correct?
I've asked this question on the Aurelia Gitter where Erik Lieben suggested to use a #processContent(function) decorator, replace the content within the given function and return true to let Aurelia process it.
Unfortunately I don't know how to actually apply those instructions and am hoping for some alternative approaches here or some details about how to actually accomplish this.
Edit
I've created a corresponding feature request. Even though possible solutions have been provided, I'd love to see some simpler way to solve this ;)
When you want to reuse HTML snippets, use compose. Doing so does not create a new custom element. It simply includes the HTML at the location of each compose element. As such, the view-model for the included HTML is the same as for the element into which it is composed.
Take a look at this GistRun: https://gist.run/?id=36cf2435d39910ff709de05e5e1bedaf
custom-link.html
<template>
<button if.bind="!isLinkBtn">
<compose view="./custom-link-icon-and-text.html"></compose>
</button>
<a if.bind="isLinkBtn" href="#">
<compose view="./custom-link-icon-and-text.html"></compose>
</a>
</template>
custom-link.js
import {bindable} from 'aurelia-framework';
export class CustomLink {
#bindable() contentText;
#bindable() icon;
#bindable() isLinkBtn;
}
custom-link-icon-and-text.html
<template>
<span class="btn-icon">${icon}</span>
<span class="btn-text">${contentText}</span>
</template>
consumer.html
<template>
<require from="./custom-link"></require>
<custom-link content-text="Here is a button"></custom-link>
<custom-link is-link-btn.bind="true" content-text="Here is a link"></custom-link>
</template>
You may want to split these into separate elements, like <custom-button> and <custom-link> instead of controlling their presentation using an is-link-btn attribute. You can use the same technique to reuse common HTML parts and composition with decorators to reuse the common code.
See this GistRun: https://gist.run/?id=e9572ad27cb61f16c529fb9425107a10
Response to your "less verbose" comment
You can get it down to one file and avoid compose using the techniques in the above GistRun and the inlineView decorator:
See this GistRun: https://gist.run/?id=4e325771c63d752ef1712c6d949313ce
All you would need is this one file:
custom-links.js
import {bindable, inlineView} from 'aurelia-framework';
function customLinkElement() {
return function(target) {
bindable('contentText')(target);
bindable('icon')(target);
}
}
const tagTypes = {button: 'button', link: 'a'};
#inlineView(viewHtml(tagTypes.button))
#customLinkElement()
export class CustomButton {
}
#inlineView(viewHtml(tagTypes.link))
#customLinkElement()
export class CustomLink {
}
function viewHtml(tagType) {
let result = `
<template>
<${tagType}${tagType === tagTypes.link ? ' href="#"' : ''}>
<span class="btn-icon">\${icon}</span>
<span class="btn-text">\${contentText}</span>
</${tagType}>
</template>
`;
return result;
}
Sorry, I was doing 2 things at once while looking at gitter, which I am not good at apparently :-)
For the thing you wanted to accomplish in the end, could this also work?
I am not an a11y expert or have a lot of knowledge on that area, but from what I understand, this will accomplish what you want. The browser will look at the role attribute and handle it as a link or button and ignores the actual element type itself / won't care if it is button or anchor it will act as if it is of the type defined in role.
Then you can style it like a button or link tag with css.
<a role.bind="type"><span>x</span><span>y</span></a>
where type is either link or button, see this: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/ARIA_Techniques/Using_the_link_role

Soundcloud waveform nodes

I was reading a article on soundcloud today about their waveforms and how they generate them by converting the highest volume point into a INT between 0 - 1.
After that I opened the console on chrome and then a track on Soundcloud, going through the networks tab (all files) there was no file returning a array of data to generate the html5 waveform, so my question is how do they do it without requesting the data?
Interesting question :) I'm no expert at HTML5's canvas, but I'm sure it has to do with that.
If you look at the DOM you'll see a structure like this:
<div class="sound__body">
<div class="sound__waveform">
<div class="waveform loaded">
<div class="waveform__layer waveform__scene">
<canvas aria-hidden="true" class="g-box-full sceneLayer" width="453" height="60"></canvas>
<canvas aria-hidden="true" class="g-box-full sceneLayer waveformCommentsNode loaded" width="453" height="60"></canvas>
<canvas aria-hidden="true" class="g-box-full sceneLayer" width="453" height="60"></canvas>
</div>
<div class="commentPlaceholder g-z-index-content">...</div>
<div class="commentPopover darkText smallAvatar small">...</div>
</div>
</div>
</div>
On my page I have four sounds. In my networkpanel I also have four of these:
https://wis.sndcdn.com/iGZOEq0vuemr_m.png
They are being sent as JSON, not as PNG!
And contain stuff like:
{"width":1800,"height":140,"samples":
[111,116,118,124,121,121,116,103,119,120,118,118,119,123,128,128,119,119,119,120,117,116,123,127,124,119,115,120,120,121,120,120,121,121,117,116,117,120,123,119,121,125,128,126,122,99,119,120,121,117,122,120,125,125,134,135,130,126,122,123,120,124,126,124,114,111,119,120,120,118,119,132,133,128,127,
...much more
...much more
122,120,125,125,134,135,130]}
I'm pretty sure this is the data being used to draw the waveform using canvas.
As far as i understand this process.
SoundCloud creates an image directly after the upload.
You can access it via the tracks endpoint.
SC.get('/tracks/159966669', function(sound) {
$('#result').append('<img src="' +sound.waveform_url+'"/>' );
});
I.e. http://jsfiddle.net/iambnz/fzm4mckd/
Then they use a script like that, written by (former) SoundCloud devs, http://waveformjs.org - which converts the image into floats.
Example call:
http://www.waveformjs.org/w?url=https%3A%2F%2Fw1.sndcdn.com%2FzVjqZOwCm71W_m.png&callback=callback_json1
Example response (extract)
callback_json1([0.07142857142857142,0.5428571428571428,0.7857142857142857,0.65,0.6142857142857143,0.6357142857142857,0.5428571428571428,0.6214285714285714,0.6357142857142857,0.6571428571428571,0.6214285714285714,0.5285714285714286,0.6642857142857143,0.5714285714285714,0.5,0.5,0.6,0.4857142857142857,0.4785714285714286,0.5714285714285714,0.6642857142857143,0.6071428571428571,0.6285714285714286,0.5928571428571429,0.6357142857142857,0.6428571428571429,0.5357142857142857,0.65,0.5857142857142857,0.5285714285714286,0.55,0.6071428571428571,0.65,0.6142857142857143,0.5928571428571429,0.6428571428571429,...[....]
See example here, more detailed on waveform.js
HTML
<div class="example-waveform" id="example2">
<canvas width="550" height="50"></canvas>
</div>
JS
SC.get('/tracks/159966669', function(sound) {
var waveform = new Waveform({
container: document.getElementById("example2"),
innerColor: "#666666"
});
waveform.dataFromSoundCloudTrack(sound);
});
http://jsfiddle.net/iambnz/ro1481ga/
See docs here: http://waveformjs.org/#endpoint
I hope this will help you a bit.

Add class to parent of <img> with certain class name or certain source

My HTML looks like this, and I'm working with the YUI library:
<div>
<img class="smallimage" src="host/smallimage.jpg">
</div>
<div>
<img src="host/bigimage.jpg">
</div>
I would like to know how to (1) add a class to the container off all images with the class of .smallimage as well as (2) add a class to the container of all images with the string 'big' in the source tag. :)
So that the output is like this:
<div class = "small">
<img class="smallimage" src="host/smallimage.jpg">
</div>
<div class = "big">
<img src="host/bigimage.jpg">
</div>
Thanks very much fellas!
UPDATE:
Fellas I think I have figured this out now, but would still apprecate if someone could maybe just look if its solid:
1)
YUI().use('node', function(Y)
var node = Y.one(".smallimage")
Y.one(".smallimage").get('parentNode').addClass("small");
});
2)
YUI().use('node', function(Y)
var node = Y.one("img[src*='big']")
Y.one("img[src*='big']").get('parentNode').addClass("big");
});
Thanks!
Your solution is correct, but as the function says using Y.one will affect only one element. If you have multiple images you should use Y.all.
Also, keep in mind that you can do everything inside one YUI().use() call.