Aurelia call function on component from button - aurelia

If I have a custom component with it's own function.
export class ModalWindow {
public modalelement: HTMLElement;
show() {
$(this.modalelement).modal('show');
}
}
Is there a way of exposing show() for other elements (like a button on my page) to call?
<modal-window></modal-window>
<button click.delegate="modal-window.show()">Show modal</button>

Flipping heck, spent ages trying to work this out and finally decided to post here.
5 minutes later, I work it out:
<modal-window view-model.ref="addmodal"></modal-window>
<button click.delegate="addmodal.show()">Show modal</button>
I am happy to hear of any better options if you can think of anything?

Related

Lazy loading data from API in Vue.js

I want to lazy load content when the user scrolls down to the bottom of the Bootstrap modal, sort of like an infinite scroll, using Vue.js. I'm fetching all my data from a action method on API call. The data coming from this API is stored in array of objects on mounted and is used in the application.
So far so good. But now I want to implement that in the initial state, only the first 10 items are fetched from the API. When the user scrolls down to the bottom of the page I want to fetch the next 10 results and so on. I've looked at the documentation of the API that I'm using, and it has support for offsetting the items I'm fetching. Though I'm not sure where to start from there. Does anyone know any good resources on this subject? Thanks a ton!
after a while i solved the problem
here is my sample project for you reading this question
Here is my solution if you are trying to avoid using an npm package. You can use it in any scrollable div in vue. And in the if statement below is where you would handle your api call to fetch more results.
<template>
<div class="scroll" #scroll="scroll">
</div>
</template>
<script>
export default{
name: "Scroll",
data(){
return{
bottom: false
}
},
methods:{
scroll(e){
const {target} = e;
if (Math.ceil(target.scrollTop) >=
target.scrollHeight - target.offsetHeight) {
//this code will run when the user scrolls to the bottom of this div so
//you could do an api call here to implement lazy loading
this.bottom = true;
}
}
}
</script>

How to add a click function to an imported component in Vue

So I have a Vue2 app. I have create a component "u-button"
when i import this and use it in another component, I want to be able to add a click function to it. However at the moment it looks for a function on the u-button component rather than the component it is being used in.
so for example, in the below if i click the first button nothing happens, if i click the second button i get the console log.
<template>
<div>
<u_button #click="clicked">Click me</u_button>
<button #click="clicked">Click me</button>
</div>
</template>
<script>
import u_button from '../components/unify/u_button'
export default {
components: {
u_button
},
methods: {
clicked() {
console.log("Working!");
}
}
}
</script>
However if i add a method on the u-button component, then it calls that. So how can i get my below example to work ? The only thing I can think of is to wrap it in another div and add the click function to that. but I'm wondering if there is a better way?? I dont want to use events to do this either as that gets messy very quickly.
As you can imagine having a reusable button that when clicked always performs the same function is a bit pointless.
It's because of the nature of components for example if we had a (virtual) iframe component which had a button in it and we'd like to detect click event on it we might name the event click and listen for it in the parent component; therefore, Vue introduced a feature called event modifiers for example in Vue, We have .native modifier (you can read more about the Vue modifiers here)
Now, to make your code work, You should add a .native after #click like this:
<u_button #click.native="clicked">Click me</u_button>
By the way, it's better to develop a naming convention for yourself It'd become handy when your projects get larger.

Best way to load page data into div with VueJS

I have been doing a lot of VueJS tutorials including the router, event bus, and trying to use fetchival and axios to no avail.
The setup, I want there to be two sections. One where I have buttons and the second section would be updated with html data from html files that varies depending on the button pressed.
I have used event bus to be able to just update the second div with basic, static html
(i.e. <p>got it</p>) but I cannot, for the life of me, use any request to get html from another website or file and load it into the div.
I don't necessarily need anyone to build it for me, but even some guidance and direction would be infinitely appreciated.
Based on your comments above, I think you want to change your thinking from "loading html files" to "showing different parts of the Vue component."
Here's a basic example. I'm going to use Vue single-file component syntax, but it's not hard to refactor for class-based components:
<template>
<div>
<button #click="clickedShowFirst">Show First</button>
<button #click="clickedShowSecond">Show Second</button>
<div v-if="showingFirst">
This is the first section!
</div>
<div v-else>
This is the second section!
</div>
</div>
</template>
<script>
export default {
data: function () {
return {
// We default to showing the first block
showingFirst: true
}
}
methods: {
clickedShowFirst: function () {
this.showingFirst = true
},
clickedShowSecond: function () {
this.showingFirst = false
}
}
}
</script>
You could of course make each of the v-if blocks components of their own that you import (which makes sense if they are complex themselves).
Or as suggested by Phillipe, you can use vue-router and make each of those views a different page with a different URL.
One last recommendation to leave you with, I found Jeffrey Way's Laracasts series on Vue.js amazingly helpful when I was learning. His episode titled "Exercise #3: Tabs" is very similar to what you're asking here.
You could use vue-router (https://router.vuejs.org/en/). In first section put the router-link (https://router.vuejs.org/en/api/router-link.html), your buttons, in second section put the router-view (https://router.vuejs.org/en/api/router-view.html).

Aurelia EventAggregator not subscribing

I have a parent-child component architecture in my Aurelia app. Panel is a Parent component View-model, inside which there is a Tool component.
I have a pagination UI on Panel, clicking on which the Tool should update. The problem is, the variable which keep track of which page number was clicked, pageNumber is only available in panel.ts and not available in tool.ts. So basically, this is an issue of communicating between two ViewModels.
To solve this issue, I am using Aurelia's EventAggregator by following this excellent tutorial. Here is what I have written till now:
panel.html
<a class="page-link" click.delegate="pageClick(1)"> 1 </a>
panel.ts
import {inject} from 'aurelia-framework';
import {EventAggregator} from 'aurelia-event-aggregator';
#inject(EventAggregator)
export class Panel {
eventAggregator: EventAggregator;
constructor(eventAggregator) {
this.eventAggregator = eventAggregator;
}
pageClick(pageNumber) {
var pageInfo = {
pageNumber: pageNumber
}
this.eventAggregator.publish("pageClicked", pageInfo);
}
tool.ts
import {inject} from 'aurelia-framework';
import {EventAggregator} from 'aurelia-event-aggregator';
#inject(EventAggregator)
export class Tool {
eventAggregator: EventAggregator;
constructor(eventAggregator) {
this.eventAggregator = eventAggregator;
}
pageClicked() {
this.eventAggregator.subscribe("pageClicked",
pageInfo => {
console.log(`${pageInfo.pageNumber} was clicked`);
});
}
This works fine until the event is fired. I tried debugging and saw that eventAggregator fired the pageClicked event. But the breakpoint on subscribe was never hit. Somehow the subscribe method is not triggered. What am I missing here?
My initial thought is that EventAggregator instance is different, but I am not sure if it needs to be same. Any help is appreciated. Also, if you know some other better way to achieve intercomponent communication please let me know how. Thanks.
You need to set up the subscription in a function that will be called. Maybe add an attached callback and set up the subscription there. Make sure to dispose the subscription, probably in a detached callback. I'm on mobile right now, but if you need a code example, let me know, and I'll add one when I get home.

Registering EVent Listeners inside the dojo .addOnload Method or declaraitevly

What is the difference between using registering Event Listeners inside the dojo .addOnload Method or declaraitevly registering them ??
For example i have a Button as shown
<button dojoType="dijit.form.Button" id="buttonTwo">
Show Me!
</button>
1st Approach :
dojo.addOnLoad(function() {
var widget = dijit.byId("buttonTwo");
dojo.connect(widget, "onClick", function(){
alert('ddddd');
});
2nd Approach :
<button dojoType="dijit.form.Button" id="buttonTwo" onClick="callMe()">
Show Me!
</button>
There is no practical difference, it is a matter of how you prefer to organize your code.
Having said this, I believe you should avoid mixing declarative and programmatic approaches in Dojo, in order to have a more coherent code base. Which means if you chose the programmatic route, you should do something like this, instead of your 1st approach:
dojo.addOnLoad(function() {
new dijit.form.Button(
{
label: "Show Me!",
onClick: function() {
alert('ddddd');
}
},
'buttonTwo'
);
});
...
<button id="buttonTwo"></button>
This example is a full programmatic example. Depending on your preference you can use it (instead of your 1st approach), or use your second approach. You can read more about the differences in programmatic and declarative Dojo approaches here.