Combining Vue v-for with GSAP transitions - javascript

I have two components, one that generates a bunch of divs
<div
v-for="(app, index) in items.apps"
ref="appIcon"
:key="index"
>
<div #click="openApp(app)"></div>
</div>
with a method that pushes the clicked div into an array of openedApps
openApp(appName) {
this.items.openedApps.push(appName)
}
then, in a separate component, the array of apps is generated dynamically based on it's content
<div
v-for="(app, index) in items.openedApps"
ref="appWindow"
:key="index"
>
</div>
and I want to make transitions for all items in openedApps array, but separately, preferably using GSAP.
but when I do it like this
mounted() {
let { appWindow } = this.$refs
let timeline = new TimelineLite()
timeline.from(appWindow, 1, {opacity:0})
}
nothing happens and I get an error from GSAP saying "GSAP target undefined not found".
So I'm guessing there's something wrong with the usage of mounted() hook here, but I have no clue what to do. Been hitting my head against the wall on this one for two days trying to figure it out because I really want to use GSAP for this project instead of just the standard , but I just dont know how to succesfully target certain divs using GSAP and Vue.

Related

How to dynamically render videos in a vue carousel?

I am working with a video carousel using video.js and vueslickcarousel, these two library. The current code is as below:
<template>
<div>
<VueSlickCarousel
ref="carousel"
v-bind="settings"
#beforeChange="onSlideBeforeChange"
>
<carousel-video
v-for="video in visibleVideos"
....
></carousel-video>
</div>
</template>
....
methods: {
onSlideBeforeChange: function(currentIndex, nextIndex) {
...calculate lowerBound, upperBound for visibleVideos.
},
},
computed: {
visibleVideos: function() {
slice from a videoArray using lowerBound and upperBound
}
}
Here visibleVideos is a computed property. I want to increase/decrease the number of <carousel-video> rendered dynamically because the list is huge and can't render all of them at once.
However when the upperBound and lowerBound update is triggerd based on some condition, the internal state of VueSlickCarousel doesn't update.
The items are rendered in dom but these two class is missing in slick-list items - slick-current slick-active. That's why nothing is shown in the view. After that, If I click the next or previous button provided by VueSlickCarousel, it removes the whole component from dom.
Before updating upperBound and lowerBound
After update of upperBound/lowerBound
How can I fix this? Or is there any other library or way to efficiently render video.js videos in a carousel? Any similar implementation or opensource example will also be equally helpful.
Thanks in advance for any kind of help or suggestion.

How to correctly plugin in a Reactjs Scroll bar module

I'm taking the simple Facebook flux-chat example and plugging in nicer scroll bars for the "MessagesSection" component
The plugin in for the scrollbars is here
I installed the module, required it in the "MessagesSection" and wrapped the new component around the list of messages like so:
render: function() {
var postListItems = this.state.posts.map(getPostListItem);
return (
<div className="post-section">
<h3 className="post-thread-heading">{this.state.thread.name}</h3>
<ul className="post-list" ref="postList">
<ScrollbarWrapper>
<div>
{postListItems}
</div>
</ScrollbarWrapper>
</ul>
<PostComposer threadID={this.state.thread.id}/>
</div>
);
}
**Note: I also tried wrapping it around the unordered list as well.
Yet the scroll bars remain unchanged(still the basic chrome ones that were there before).
What am I doing wrong that the scroll bars are not changing?
Copy paste this CSS in the index.html: https://github.com/ojame/react-scrollbars/blob/master/examples/views/home/examples/custom-scrollbar.css
And use the class on the wrapper like so: <ScrollbarWrapper className="ScrollbarContent--custom">

Polymer, evaluate element based off object

I am using the tile example from polymers neon elements - and I am trying to make each expanded tile unique. My first try on how to do this was to pass a string in with the grid items like
{
value: 1,
color: 'blue',
template: 'slide-1'
}
And have that element be evaluated when rendered in a new element something like this. (this is the card template itself)
<template>
<div id="fixed" class$="[[_computeFixedBackgroundClass(color)]]"></div>
<div id="card" class$="[[_computeCardClass(color)]]">
<[[item.template]]></[[item.template]]>
</div>
This does not work - however I am wondering if there is some way to do this so I can load custom elements for the content of each card. For reference -https://elements.polymer-project.org/elements/neon-animation?view=demo:demo/index.html&active=neon-animated-pages , it is the grid example and I am trying to replace the content of each card once it is clicked on ( the fullsize-page-with-card.html, here is all the html for it - https://github.com/PolymerElements/neon-animation/tree/master/demo/grid ). Is this the wrong way of approaching this? Or maybe I have some syntax wrong here. Thanks!
Edit : OK, So I can send it through if i add it to the click to open the card like so
scope._onTileClick = function(event) {
this.$['fullsize-card'].color = event.detail.data.color;
this.$['fullsize-card'].template = event.detail.data.template;
this.$.pages.selected = 1;
};
and in the card's properties like so
template: {
type: String
},
So I can then evaluate it as [[template]] , however - the question still remains how to call a custom element (dynamically) using this string. I could pass a couple of properties and fill in a card or form so they are unique, but i think I would have much more creative freedom if I could call custom elements inside each card.
I have an element that allows referenced templates. There are a couple of others other there, but this one also allows data bindings to work: https://github.com/Trakkasure/dom-bindref

polymer - how to get next corresponding element in a repeating template?

sorry for the sort of specific question. I'm trying to make an accordion using core-collapse and repeating templates and am facing some difficulties. Here is my accordion repeating template:
<template repeat="{{item, i in items}}">
<div class="accordheader" on-click="{{toggle}}">{{item}}</div>
<template repeat="{{content, i in contents}}">
<core-collapse class="collapse">
<p>{{content}}</p>
</core-collapse>
</template>
</template>
and here is my script:
toggle: function () {
//get whichever 'accordheader' clicked on
var collapseGetting = this.shadowRoot.querySelector('.accordheader');
console.log(collapseGetting);
//find the core-collapse that is directly underneath it
var collapse = $(collapseGetting).next('core-collapse');
console.log(collapse);
//toggle that particular core-collapse
collapse.toggle();
console.log('toggled');
}
And now my toggle is entirely broken and won't actually toggle anything. I still receive the 'toggled' console log but nothing is happening. I'm not sure if I'm targeting the next core-collapse correctly, or even nesting the repeating templates correctly. Basically I have 2 arrays, [items] and [contents] which I am retrieving my item for each .accordheader and my content for each core-collapse.
Any insight? I feel like this is a formatting or template issue..
Having a quick peek at the docs here:
http://www.w3schools.com/jquery/traversing_next.asp
(See the 'Try It Yourself' example')
I believe you're current code is getting the next '.accordheader' element instead of the next 'core-collapse'.
If I've interpreted the link properly then it should look something like this:
$('core-collapse').Next( console.log(collapse); );
Never used 'Next' before, but there's my 5 cents.

Reactjs append an element instead of replacing

I'm trying to iterate through a list/array/object of things: (I used coffeescript to keep it clear, jsfiddle of full JS here. but it's just a forEach)
pages = for page, each of #props.ids
$('#start').append("<div id='"+page+"' ></div>")
React.renderComponent page(title: each.title, text: each.text), $("#"+page)[0]
and append each of them, instead of replacing, leaving only the last item in the list.
Where the #start element is the starting container, and I want to populate it with multiple elements, but I need to give each their own container, otherwise they will all overwrite eachother, the default reactjs behaviour.
I'm wondering if there's a way to tell react to append instead of replacing the div.
I'd like to avoid using jquery if possible, and do it purely react-ly.
I though about giving the React.renderComponent page the initial list, and then iterate in the previously called template, however, then i'm facing a different problem, I have to return a reactjs element object, consisting of the whole list, which I really don't prefer.
I need for the initial call to create individual, independent react templates, appending eachother in a list, prefferably without any extra containers, or using jquery.
I think you're getting the concept wrong. React's renderComponent indeed renders a single component, somewhere. Doing this multiple times only re-renders the same component at that place (aka idempotent). There's no real "append" statement, at least not in the way you asked for.
Here's an example of what you're trying to achieve. Forgot about renderComponent in this. It's just to put the component somewhere.
/** #jsx React.DOM */
var pages = [{title: 'a', text: 'hello'}, {title: 'b', text: 'world'}];
var App = React.createClass({
render: function() {
return (
<div>
{
this.props.pages.map(function(page) {
return <div>Title: {page.title}. Text: {page.text}</div>;
})
}
</div>
);
}
});
React.renderComponent(<App pages={pages} />, whateverDOMNodeYouWantItToBeOn);
See what I did there? If I want multiple divs, I just create as many as I want to see. They represent the final look of your app, so making a same div be "appended" multiple times doesn't really make sense here.
Create a div with a class extradiv:
<div class="extradiv">
</div>
In CSS, Set It's display to none:
.extradiv {
display: none;
}
.extradiv * {
display: none;
}
In JS implement this function:
function GoodRender(thing, place) {
let extradiv = document.getElementsByClassName('extradiv')[0];
ReactDOM.render(thing, extradiv);
extradiv = document.getElementsByClassName('extradiv')[0];
place.innerHTML += extradiv.innerHTML;
}
Than you can use this in place of ReactDOM.render:
GoodRender(<Component>My Text</Component>, YourDOMObject)

Categories

Resources