I'm newbie to Angular 2. What are the corresponding events from AngularJS to Angular 2?
eg: ng-click to (click)
How about ng-init and all others events? I'm not having intellisense in VS .NET, so it's hard to guess.
Any help please!
Thanks
The default handled events should be mapped from the original HTML DOM component's events:
http://www.w3schools.com/jsref/dom_obj_event.asp
by just removing the on prefix.
onclick ---> (click)
onkeypress ---> (keypress)
etc...
You can also create your custom events.
However ngInit is not an HTML event, this is part of the Angular's Component lifecycle, and in Angular 2 they are handled using "hooks", which are basically specific method names inside your component that will be called whenever the component enters the specific cycle. Like:
ngOnInit
ngOnDestroy
etc...
Here is the list of events in Angular
Please check in the documentation if required for more info
(focus)="myMethod()"
(blur)="myMethod()"
(submit)="myMethod()"
(scroll)="myMethod()"
(cut)="myMethod()"
(copy)="myMethod()"
(paste)="myMethod()"
(keydown)="myMethod()"
(keypress)="myMethod()"
(keyup)="myMethod()"
(mouseenter)="myMethod()"
(mousedown)="myMethod()"
(mouseup)="myMethod()"
(click)="myMethod()"
(dblclick)="myMethod()"
(drag)="myMethod()"
(dragover)="myMethod()"
(drop)="myMethod()"
This is one of the big advantages of Angular2. Not every event needs a customized ng-xxx directive anymore.
With custom elements and all other libraries producing all kinds of custom events, this approach doesn't fly.
In Angular2 the (eventName)="expression" binding syntax allows to subscribe to any known and unknown event.
The $event variable is still available (eventName)="myEventHandler($event)"
See also https://angular.io/docs/ts/latest/guide/template-syntax.html#!#event-binding
A great place to begin to understand Angular 2 is the official Web Page.
Here you can see all the angular2/common ng-XXX although now it is as follows ngXxxx
In my case the best way to understand the differences between Angular 1 and Angular 2 was doing the tutorials:
Tour of Heroes
The Developer Guide: this is a practical guide to Angular for experienced programmers who are building client applications in HTML and JavaScript.
You can use the following syntax to handle events (for example click like ng-click with Angular1):
<button (click)="callSomeMethodOfTheComponent()">Click</button>
The difference here is that this is more generic. I mean you can use DOM events directly but also custom ones defined using the EventEmitter class.
Here is a sample that describes how to handle a click event and a custom event (my-event) trigged by a sub component:
#Component({
selector: 'my-selector',
template: `
<div>
<button (click)="callSomeMethodOfTheComponent()">Click</button>
<sub-component (my-event)="callSomeMethodOfTheComponent()"></sub-component>
</div>
`,
directives: [SubComponent]
})
export class MyComponent {
callSomeMethodOfTheComponent() {
console.log('callSomeMethodOfTheComponent called');
}
}
#Component({
selector: 'sub-component',
template: `
<div>
<button (click)="myEvent.emit()">Click (from sub component)</button>
</div>
`
})
export class SubComponent {
#Output()
myEvent: EventEmitter;
constructor() {
this.myEvent = new EventEmitter();
}
}
Hope it helps you,
Thierry
Related
I'm using a livewire full-page component to display a list of tasks along with all the CRUD stuff associated, and using dragula to allow for drag and drop.
I initially had all this running through a TaskListComponent, and was having trouble getting some of the functionality to work so I now have a child component that just handles the task itself. So there's a TaskListComponent that's the page, and and then I have a TaskComponent that's added to the page in a foreach loop. my thought is that all the task list type functionality would happen in the main component, and anything related to the specific task (show, update, delete, etc) would be in the TaskComponent. Tell me if that's how you would structure it?
My question now is, based on that structure, I have some javascript that's running on the page to listen for the dragula drop event and handle reordering/changing status of tasks and it relies on the element ID, but since I made each task a livewire component now the element id is being replaced with wire:id which is some hash value. I don't know how to access that in javascript and get the original html element ID.
This is what's in my blade file:
#foreach ($tasks as $task)
#if ($task->task_status_id === $status->id)
<livewire:tasks.task-component wire:key="{{ $task->id }}" :task="$task" data-task-id="{{ $task->id }}" />
#endif
#endforeach
And here's the bit of js using dragula:
drag.on('drop', function(el, target, source, sibling) {
console.log(el);
});
The above console.log outputs:
<div wire:id="1pPdyV6eX8kgtePfXBzk" ...></div>
Sorry I know this is a noob question, but it's not clear from the docs how to get to what I'm after. I've tried using Livewire.find() but it returns undefined. I can use Livewire command in the console, so I know it's available.
Also possibly related, any kind of $wire command I call says $wire is undefined. I've got this in my app.js file that's loaded after livewire scripts:
import Alpine from 'alpinejs'
window.Alpine = Alpine
Alpine.start()
And I can do Alpine in the console and it knows what that is.
Any help would be greatly appreciated.
You should load your app.js file in the head of your document with a defer attribute.
You can then use $wire or this.$wire to access to the Livewire component. This only works when your Alpine component is inside of a Livewire component though.
I'm trying to figure out how to conditionally load sub/child component from Laravel's blade template
I have a main container, which is being called from the blade:
<structure-container view='menu-index'></structure-container>
Here is the StructureContainer.vue
<template>
<div>
//I can have if-else statement here by "view", but looking for a better solution
<menu-index></menu-index>
</div>
export default{
components: {
'menu-index': require('./menu/IndexComponent.vue'),
'test': require('./menu/TestComponent.vue'),
},
props: ['view']
}
As you can see I have two child components: menu-index & test. I want to pass the parameter from blade and display the corresponding component. Can I avoid if-else statements? there should be a better way to do this
You can simply bind the component name dynamically to the is property (using v-bind:is or :is), i.e.:
<div>
<component :is="view"></component >
</div>
The really awesome thing about this is that the <component> container is reactive, and you can dynamically load/unload/change the components on-the-fly. How awesome is that? :)
For more information, I encourage you to read up the documentation on dynamic components on the official docs.
I am working on a Laravel 5.2 project with Laravel Spark (which still in beta as at time of writing) and trying to add some Vuejs functionality using the default layouts and views.
My first attempt failed because I simply tried to create a new div within the home view and bind my Vue code to that div. Here is the div:
<div id="my-stuff">
<p>#{{ test }}</p>
</div>
And here is the corresponding JS code:
new Vue( {
el: '#my-stuff',
data: {
test: 'This is a test'
}
});
What I expected to see were the words "This is a test" appear within that div on the home screen, but of course nothing appeared because, as mentioned, Vue gets bound to a div immediately after the body tag (well, I'm assuming that's why anyway).
I think the solution to my problem is to use Vue components, which themselves look fairly straightforward, but I have no idea where to put my code, how to integrate my code with the Gulp process, which Spark file I need to modify (if any?) to register my component and how to ensure that my component gets registered before the Vue instance gets created.
Any help would be much appreciated.
Addendum 1
To reproduce the exact same set-up as I'm using, one would need to install a fresh copy of Laravel 5.2, then use the spark installer to add the spark stuff, then add app.js containing the code below to the public folder, add the corresponding div anywhere in the home view and add a script tag to include app.js right below the script tag that imports the main javascript file produced by gulp.
Whilst it is impractical to reproduce that entire setup in a fiddle, I think the following fiddle illustrates the essence of the problem:
https://jsfiddle.net/5oLLte2e/
From memory you have the same limitation in AngularJS. It is completely reasonable to me why this wouldn't work and the solution in Vuejs is most likely to use components, but the challenge in this situation is knowing how to bundle the component and where to save it in order to integrate it with the gulp config, or if that is even necessary.
Vuejs Components
If you want to have more than one vue instance the short answer is: yes, you need components.
<div id="main-app">
<p>{{ mainMessage }}</p>
<my-app>
<p>Some composable content</p>
</my-app>
</div>
And the scripts will have to be loaded components first:
Vue.component('my-app', {
template: '<div>{{myMessage}}<br/><slot></slot></div>',
data: function() {
return {
myMessage: 'This is my message'
}
}
});
new Vue( {
el: '#main-app',
data: {
mainMessage: 'This is the main module'
}
});
The output will be:
This is the main module
This is my message
Some composable content
Here is the fiddle: Components with Vue
Remember that you can always put the template in the page using a unique id or, more idiomatically using something like:
<script type="x/template" id="my-app">
Your template here
{{ your component variables }}
</script>
Laravel Spark Integration
The steps to adding a component within a Sparkified Laravel application are as follows:
(1) Add the placeholder HTML with the custom tag anywhere on the page, even if a surrounding div has already been Vue-ified. The HTML with the custom component might look like this:
<div id="example">
<my-component></my-component>
</div>
(2) Implement the Vue component and save the JavaScript file in resources/assets/js. By way of example, we might save the following code as my-component.js:
var MyComponent = Vue.extend({
data: function() {
return { message: 'This is a test' }
},
template: '{{ message }}'
})
Vue.component('my-component', MyComponent)
new Vue({
el: '#example'
})
(3) Add one require statement (the second line below) to the code in resources/assets/js/app.js so that the file looks like this:
require('laravel-spark/core/bootstrap');
require('./my-component.js'); // This is the key!
new Vue(require('laravel-spark'));
Note that it is super-important to include the leading ./ in front of the filename, otherwise Browserify will assume it is looking for a npm module instead of a raw file and will fail.
(4) Run gulp and once it has finished, refresh the page. Gulp will call Browserify, which processes resources/assets/js/app.js, which now includes our custom JavaScript to be processed and included in the final public/js/app.js file.
If you carry out these steps on a clean Laravel installation that has had the Spark installer treatment (I made my mods to home.blade.php), you should see the sample text appear on the page.
Tried mixing some jQuery but everything is based on appending, something I don't wanna use because i'm trying to base my design completely on binding and stamping templates and elements. I tried using scrollTop in various ways but I always ended up being depended on what's appended on the local DOM. If i'm not mistaken, dom-repeat has nothing to do with appending, but with creating the same stamp and bind it multiple times (correct me if i'm wrong, I started looking into Polymer 1 recently).
I only found this one good example of using infinite scroll over a repeating template https://github.com/chadliu23/event-infinite-scroll but unfortunately it's not what i'm looking for as I'm mixing iron-ajax parsing data into my template. Simulating chadliu23's example lead me into a silly middle step of creating an extra array and pushing data from ajax into it, but it is totally something I don't want to do cause it's messing with my repeatable template restamping.
Also realized that there are ways to create infinite scrolling-ish effects with css but can't figure out any other way to implement this but in sets of images.
Meanwhile, sadly, it seems like iron-list is nowhere near ready yet and I can't find any way to use the concept idea of core-list into polymer 1.0.
So..... Any suggestions on the table?
I think you need an item-page component:
<dom-module id="item-page">
<template>
<iron-ajax id="ajax"
params="{{_composeParamsForPage(page)}}"
last-response="{{pageData}}">
</iron-ajax>
<template is="dom-repeat" items="{{pageData}}" as="item">
<!-- Compose your list of items for this page here -->
</template>
</template>
<script>
(function(){
"use strict";
Polymer({
is: 'item-page',
properties: {
page: {
type: Number,
observer: '_updatePage(page)'
}
},
_updatePage: function(page) {
this.$.ajax.generateRequest();
}
});
})();
</script>
</dom-module>
Then, to create an infinitely scrolling list:
<template is="dom-repeat" items="{{pages}}" as="page">
<item-page page="{{page}}"></item-page>
</template>
It's important that in your item-page component the iron-ajax does not have auto set, because the page property will initially be set to undefined. Instead, you should observe page and act accordingly only once it's updated to something other than undefined.
Ember.js has a great mechanism of binding data to views, of setting triggered event handling in the view, or using a Router. But what I would need is to be able to handle events triggered in already created HTML code (by PHP, server-side).
Let me show you a simple example. I have this code:
<a id="login" href="#">Login</a>
I need to be able to route/handle the click on this link so that it gets into my Ember application.
I have been looking for ways to do this, but I can't find any.
How can I do this?
If this link is inside a DOM element which is a child of the Ember managed element, then you can use the action helper:
<a id="login" href="#" {{action doSomeStuff}}>Login</a>
This doSomeStuff event will be sent to your Ember.Router, which has to implement the handler in the appropriated route:
...: Ember.Route.extend({
doSomeStuff: function (router) {
//...
}
}),
If the link is outside your app's scope, you can register handlers on the app-related elements using JQuery:
$('a#login').click(function () {
App.router.transitionTo('the.route.path');
});
The App.router being injected at Ember app's initialization, you can access it from anywhere.
But let me say that it is not a best practice to transition from outside the router.
Last but not least, you can also pass a context to the transitionTo call.