I have created two components in Angular 2:
ReaderComponent: The one that initiates and controls all functionality to Owl Carousel (initiate, add slide, remove slide and so on)
PageComponent: Each slide is a PageComponent and has events to handle input from the user (click, pinch, doubletap)
The ReaderComponent is created at start of the application and initiates a request to a service to get all data for each of the PageComponents.
Everything works fine until we add a slide that is a PageComponent. I have tried to add the PageComponent selector to owl Carousel:
this.slider.trigger("add.owl.carousel", ["<my-page-component></my-page-component>"]);
This does add an element of <my-page-component> but does not render the template or handles any of the PageComponents events.
I have tried to add all the PageComponents to an array and render it in ReaderComponents template:
<div *ng-for="#page of pages">
<my-page></my-page>
</div>
This renders correct but by that time all pages is rendered Owl is already initiated and no pages is visible.
So to summarize all of this: I need to know how to add a custom component via javascript (in this case the add functionality of Owl)? Is this even possible? Or is there another way to handle this so that I can add PageComponent in any way?
The first method you mentioned would require you to force angular to re-check it's bindings. This is probably possible, but I don't know off the top of my head.
The second method is much easier. You can use the lifecycle events of the Page or Reader Components to trigger the adding. They are as follows:
export var LIFECYCLE_HOOKS_VALUES = [
LifecycleHooks.OnInit,
LifecycleHooks.OnDestroy,
LifecycleHooks.DoCheck,
LifecycleHooks.OnChanges,
LifecycleHooks.AfterContentInit,
LifecycleHooks.AfterContentChecked,
LifecycleHooks.AfterViewInit,
LifecycleHooks.AfterViewChecked
];
If you add a listener to your PageComponent class, you can probably use OnInit or AfterViewChecked and then get it to add it's own element reference to the carousel (basic example). From a quick look at their documentation, it doesn't look like owl supports adding a new element, so you could have the PageComponents all on your page somewhere hidden and then just add the raw html from the elementref, then remove it again in the OnDestroy function.
If you do it in ReaderComponent you should look at OnChanges or add some clever checks into the DoCheck function and then just get it to reload all items inside it (perhaps owl.reinit?). I've not used the owl carousel before so can't be more specific there I'm afraid.
These are exported from the angular class as interfaces, so you should be extending your classes from them. An example is available on the Angular 2 website here: https://angular.io/docs/ts/latest/api/lifecycle_hooks/AfterViewChecked-interface.html
Related
I'm using Fullcalendar v5 in angular js, and i'm trying to make a custom event with:
https://fullcalendar.io/docs/content-injection
eventContent: function(arg) {
return { html: constructEvent(arg) }
},
The thing is that if i add:
"<div ng-repeat='user in arg.event._def.extendedProps.users' class='avatar'>"
"<p>{{ user.name }}</p>"
"</div>"
it won't render. It's like it's outside angular's scope. Can someone tell me if there is a way to construct this with angular js logic? Or i need to use vanilla js to iterate through items. Also ng-click doens't work. I tried even with triggering safeApply digest but no results.
I just want to edit the event inside calendar with the framework i'm using, and use angular events inside it to open sidebars or to make api calls.
Rendering Events
with your line <div ng-repeat it seems that you'd like to iterate through an array of events to display on your screen. If this is the case, you simply need to render the events via the 'events' parameter.
https://fullcalendar.io/docs/event-object
Regarding eventContent (the contents of an event, such as title, subtitle, img, etc)
It looks like at the minute only React JSX Nodes are supported. Vanilla JS is your only way forward.
https://fullcalendar.io/docs/content-injection
I am using a 3rd party plugin (ngx-modialog) that has a plugin architecture and I am using its Bootstrap plugin. Unfortunately there is a bug that after you use it to open a modal window, it does not remove a class from the body tag.
I can remove it myself after the user clicks the modal using jQuery:
jQuery('body').removeClass('modal-open');
But I would like to know how can I do the exact same as the above line in Angular?
I found I could do this to get a ref to the body:
let body = document.getElementsByTagName('body');
I was hoping that might expose a removeClass method. There must be a simple way to do this, so I can abide by the rule of NO JQUERY in Angular! ;)
NOTE
I am NOT looking to use [ng-class] as I have nothing I can bind to in this scenario.
To do that in Angular 4, you can use the Renderer2 class
Use the method: removeClass(el: any, name: string): void
Renderer2 is an abstraction provided by Angular to manipulate elements of your app without having to touch the DOM directly
You can import Renderer2 like this:
import {Renderer2} from '#angular/core';
Inject it in the constructor of your component:
constructor(private renderer: Renderer2){
}
Remove a class:
this.renderer.removeClass('body', 'modal-open');
As pointed out in the comments, the 'body' is outside of the domain of Angular - Angular loads its component hierarchy inside it.
So therefore I just need to fall back to regular javascript to do this:
document.body.className = document.body.className.replace('modal-open','');
Thanks to this question. No jQuery needed. But the accepted answer is the 'angular way' to do this, which is what I was after.
I am create an app to drag a component(angular2 component, same below) from a list and drop it into another component. In this process I used interactjs to drag and drop component. But when I drop it into another component, It only load the static html in the component template which dragged.
For example I have this component to be added into another
import {Component, View} from 'angular2/angular2'
#Component{
selector:"sample"
}
#View{
template:`<p>static content</p><p>{{contentToBind}}</p>`
}
class Sample{
contentToBind:string= "I am the binding content."
}
when it added, it should looks like below
static content
I am the binding content.
But actually it just display static content like
static content
You can check this example in this plunker.
And then I bind a click HostListener to this Sample component, when I click the component has been already added into another component, "I am binding content" will appear(other event triggered is same).
I think due to interact it has jumped out of angular2's lifecycle.
Any similar method as $apply() in angularJs 1.x?
Interact is not a part of angular 2, maybe your code in Interact is out of angular 2 scope as you said.
You can use NgZone in your Interactjs file in plunker, I edit your code and it's worked now. You should send your event inside of NgZone.
something like this.
myParent.ngZone.run(
() => {
console.log("onDrop...");
ce.drop("Hello");
}
);
See it on plunker
Plunker
I'm a total newbie to Onsen UI and I managed to make my first little app (static that is) with a few pages, popovers, lists, etc.
But when I try to add dynamic stuff in there, it does not want to cooperate.
When I click my side menu, it calls menu.setMainPage and in the callback I want to modify the content of the list (lets say iterate a JSON request and add a ons-list-item for each of them). However, they do not look styled with Onsen UI icing.
I guess it's because the menu.setMainPage has already parsed the ons-page and showed it in the browser.
Is there a way to do a load page, update the dom, and then pass it to be displayed?
I have a simila problem with an popover that contains a list. I want to add items in that list, but my jQuery append never work. Same reason I suppose.
Thanks!
Sounds like you're not running ons.compile() on the dynamic elements. The custom elements must be compiled after they've been added to the DOM to get the correct style and behavior.
I made a short example to illustrate it:
ons.bootstrap();
var addItem = function() {
var $myList = $("#my-list"),
$item = $("<ons-list-item>").text(Math.random());
$myList.append($item[0]);
ons.compile($item[0]);
};
If you attach the addItem function to a click handler you can add items dynamically to an <ons-list>.
This is a running example on codepen:
http://codepen.io/argelius/pen/gbxNEg
I am adding components to a panel at runtime:
Ext.define("MyApp.view.SomePanel",{
extend:'Ext.panel.Panel',
...
setGridList:function(gridIds) {
myItems=[];
Ext.each(gridIds,function(gridId){ myItems.push(Ext.getCmp(gridId) || Ext.create("Ext.grid.Panel",{id:gridId}))});
Ext.applyIf(me,{items:myItems});
}
});
It works well when called for the first time, from the initComponent. But it does not work when called from a store load handler. My best guess is that I have to refresh the view, rebuild the layout or sth. like that!? But I don't find such a thing in the docs.
Anyone here knows the trick?
If your class MyApp.view.SomePanel is an Ext component, than you could use the Container.add() or Container.remove().
If the child is not automatically added, call the Container.doLayout() method.
PS: the layout of your class should support multiple children.