slick slider creating last slide empty Angular JS? - javascript

Can users please explain why they are downvote this question?
Facing a problem in a slick slider that it creating an empty slide at last below is my code that is written in Angular JS. How can I deactivate or remove that empty slide?
<slick dots=false infinite=true speed=300 slides-to-show=3 touch-move=false slides-to-scroll=1 init-onload=true data="city_section">
<div ng-repeat="city_s in city_section" >
<img ng-if="city_s.search_city_image" src="<?php echo UPLOAD_PATH ?>city/{{city_s.search_city_image}}" class="img-responsive">
</div>
</slick>

Usage
Using bower to install it. bower install angular-slick-carousel
Add jquery, angular, slick-carousel and angular-slick-carousel to your code.
<script src="../bower_components/jquery/jquery.js"></script>
<script src="../bower_components/angular/angular.js"></script>
<script src="../bower_components/slick-carousel/slick/slick.js"></script>
<script src="../bower_components/angular-slick-carousel/dist/angular-slick.min.js"></script>
Add the sortable module as a dependency to your application module: slickCarousel
var myAppModule = angular.module('MyApp', ['slickCarousel'])
This directive allows you to use the slick-carousel plugin as an angular directive. It can be specified in your HTML as either a attribute or a element.
<slick infinite=true slides-to-show=3 slides-to-scroll=3>
...
</slick>
<slick
settings="slickConfig" ng-if="numberLoaded">
</slick>
Attributes & Event
settings: optional Object containing any of the slick options. Consult here.
enabled should slick be enabled or not. Default to true. Example below
method optional containing slick method. discussed below in detail
event optional containing slick event
$scope.slickConfig = {
enabled: true,
autoplay: true,
draggable: false,
autoplaySpeed: 3000,
method: {},
event: {
beforeChange: function (event, slick, currentSlide, nextSlide) {
},
afterChange: function (event, slick, currentSlide, nextSlide) {
}
}
};
Enable/disable slick
Slick can be easily switched on and off by using enabled settings flag.
$scope.slickConfig = {
enabled: true,
}
$scope.toggleSlick = function() {
$scope.slickConfig.enabled = !$scope.slickConfig.enabled;
}
<slick settings="slickConfig">
...
</slick>
<button ng-click="toggleSlick()">Toggle</button>
Method
All the functions in the plugin are exposed through a control attribute.
To utilize this architecture, and have two-way data-binding, define an empty control handle on scope:
$scope.slickConfig = {
method: {}
}
Pass it as the value to control attribute. Now, you can call any plugin methods as shown in the example.
<button ng-click="slickConfig.method.slickGoTo(2)">slickGoTo(2)</button>
<button ng-click="slickConfig.method.slickPrev()">slickPrev()</button>
<button ng-click="slickConfig.method.slickNext()">slickNext()</button>
<button ng-click='slickConfig.method.slickAdd("<div>New</div>")'>slickAdd()</button>
<button ng-click='slickConfig.method.slickRemove(3)'>slickRemove(3)</button>
<button ng-click='slickConfig.method.slickPlay()'>slickPlay()</button>
<button ng-click='slickConfig.method.slickPause()'>slickPause()</button>
Slide data
For change slide content, you have to set ng-if to destroy and init it
controller:
$scope.number = [{label: 1}, {label: 2}, {label: 3}, {label: 4}, {label: 5}, {label: 6}, {label: 7}, {label: 8}];
$scope.numberLoaded = true;
$scope.numberUpdate = function(){
$scope.numberLoaded = false; // disable slick
//number update
$scope.numberLoaded = true; // enable slick
};
html:
<script type="text/ng-template" id="tpl.html">
<h3>{{ i.label }}</h3>
</script>
<slick ng-if="numberLoaded">
<div ng-repeat="i in number">
<div class="" ng-include="'tpl.html'"></div>
</div>
</slick>
Global config
config(['slickCarouselConfig', function (slickCarouselConfig) {
slickCarouselConfig.dots = true;
slickCarouselConfig.autoplay = false;
}])
https://www.npmjs.com/package/angular-slick-carousel

Related

handle JavaScript plugin through angular js

I am new to AngularJS. I am developing a music app through AngularJS.
For HTML5 player I am using this: https://github.com/DIYgod/APlayer.
How to wrap aplyer inside angular so i only call directive to initialise player.
ex- INIT PLAYER
<div id="player1" class="aplayer"></div>
JS
var ap = new APlayer({
element: document.getElementById('player1'), // Optional, player element
narrow: false, // Optional, narrow style
autoplay: true, // Optional, autoplay song(s), not supported by mobile browsers
showlrc: 0, // Optional, show lrc, can be 0, 1, 2, see: ###With lrc
mutex: true, // Optional, pause other players when this player playing
theme: '#e6d0b2', // Optional, theme color, default: #b7daff
mode: 'random', // Optional, play mode, can be `random` `single` `circulation`(loop) `order`(no loop), default: `circulation`
preload: 'metadata', // Optional, the way to load music, can be 'none' 'metadata' 'auto', default: 'auto'
listmaxheight: '513px', // Optional, max height of play list
music: { // Required, music info, see: ###With playlist
title: 'Preparation', // Required, music title
author: 'Hans Zimmer/Richard Harvey', // Required, music author
url: 'http://7xifn9.com1.z0.glb.clouddn.com/Preparation.mp3', // Required, music url
pic: 'http://7xifn9.com1.z0.glb.clouddn.com/Preparation.jpg', // Optional, music picture
lrc: '[00:00.00]lrc here\n[00:01.00]aplayer' // Optional, lrc, see: ###With lrc
}
});
I am trying to use it by directive and pass template as
<div id="player1" class="aplayer"></div>
but I don't know how to add Aplayer JS to Angular.
You can initialize APlayer in a directive this way.
Use either <div class="aplayer"></div> or <div aplayer></div>
Attributes are declared using kebab-case in html code but you have to use camelCase to access them in directive code.
Note: data prefix is not required here. It's only used to prevent native html attribute collision.
(function() {
'use strict';
angular.module('app', []);
angular
.module('app')
.directive('aplayer', aplayer);
function aplayer() {
return {
restrict: 'AC',
link: function(scope, element, attrs) {
// `element` is the angular element the directive is attached to
// APlayer need the native one
var nativeElement = element[0];
var ap1 = new APlayer({
element: nativeElement,
narrow: false,
autoplay: true,
showlrc: false,
mutex: true,
theme: '#e6d0b2',
preload: 'metadata',
mode: 'circulation',
music: {
title: attrs["playerTitle"],
author: attrs["playerAuthor"],
url: attrs["playerUrl"],
pic: attrs["playerPic"]
}
});
ap1.on('play', function() {
console.log('play');
});
ap1.on('play', function() {
console.log('play play');
});
ap1.on('pause', function() {
console.log('pause');
});
ap1.on('canplay', function() {
console.log('canplay');
});
ap1.on('playing', function() {
console.log('playing');
});
ap1.on('ended', function() {
console.log('ended');
});
ap1.on('error', function() {
console.log('error');
});
}
};
}
})();
<!doctype html>
<html lang="en" ng-app="app">
<head>
<meta charset="utf-8">
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.4/angular.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/aplayer/1.6.0/APlayer.min.js"></script>
<script src="script.js"></script>
</head>
<body>
<div class="aplayer"
data-player-title="Preparation"
data-player-author="Hans Zimmer/Richard Harvey"
data-player-url="http://devtest.qiniudn.com/Preparation.mp3"
data-player-pic="http://devtest.qiniudn.com/Preparation.jpg"></div>
</body>
</html>

how to use ng-repeat search filter with owl carousel without braking it

I am using ng-repeat to view PS4 games data from json file inside a owl carousel like that:
<data-owl-carousel class="owl-carousel" data-options="{navigation: true, pagination: false, rewindNav : false}">
<owl-carousel-item ng-repeat="game in $ctrl.games | filter: $ctrl.query" class="item">
<a href="#!/games/{{game.id}}" class="thumb">
<img ng-src="{{game.imageUrl}}" />
<p id="gamenamebox"> {{game.name}} </p>
</a>
<p> Genre: {{game.genre}} </p>
now as you can see i added a filter for $ctrl.query and just added it to a search input like that:
Search for game:
<input ng-model="$ctrl.query"/>
now, everything is working great, all info is in the carousel and looks like this:
working great
but once i search in the search input and delete the game name i was searching for everything breaks to a line like that:
breaks
Does anyone know how can i fix it?
Thanks in advance.
this is the javascript code by the way:
.directive("owlCarousel", function() {
return {
restrict: 'E',
transclude: false,
link: function (scope) {
scope.initCarousel = function(element) {
// provide any default options you want
var defaultOptions = {
};
var customOptions = scope.$eval($(element).attr('data-options'));
// combine the two options objects
for(var key in customOptions) {
defaultOptions[key] = customOptions[key];
}
// init carousel
$(element).owlCarousel(defaultOptions);
};
}
};
})
.directive('owlCarouselItem', [function() {
return {
restrict: 'E',
transclude: false,
link: function(scope, element) {
// wait for the last item in the ng-repeat then call init
if(scope.$last) {
scope.initCarousel(element.parent());
}
}
};
}]);

Using Masonry.JS and Vue.JS

I know how to use masonry.js apart from vue. However, I'm having issue getting it to function and be called correctly inside of the vue framework. I called it inside of the created or ready but neither seem to get the grid to form correctly. How can i get this to work inside the framework? Oh and I do have jquery called in the html before this script. Here is what I have inside the component :
Edit:
I can see that the masonry is effecting the grid by assigning its height with JS and changing the items to position absolute. However, its not placing them correctly. Its stacking them ontop eachother instead of sideby side like it should be in the grid.
<template>
<div class="projects--container">
<div class="inner-section inner--options">
<div class="grid">
<div class="grid-item"></div>
<div class="grid-item"></div>
<div class="grid-item"></div>
</div>
</div>
</div>
</template>
<script>
export default{
ready: function () {
this.mason();
},
data: function () {
return {
options: [
{
option: 'projects',
phrase: 'for clients',
slogan: 'slogan...'
},
{
option: 'sides',
phrase: 'for us',
slogan: 'we love what we make'
},
{
option: 'moments',
phrase: 'with the crew'
}
]
}
},
methods: {
revert: function () {
this.$dispatch('return-home', true)
},
mason: function () {
var $grid = $('.grid').masonry({
itemSelector: '.grid-item',
columnWidth: 250
});
$grid.masonry('layout');
}
},
events: {
'option-select': function (option) {
}
}
}
</script>
As I saw it, most mv* frameworks like vue keep DOM elements (view) in sync with js (model), in the other hand, frameworks like masonry just need valid DOM to work.
So, the tricky part is to tell one to another when DOM has changed.
So the first change is when vue finished to render all DOM, as mentioned in other answers, we are notified on mounted lifecycle hook, here is where we can initialize masonry
mounted() {
let grid = document.querySelector('.grid');
this.msnry = new Masonry(grid, {
columnWidth: 25
});
},
In any other change to our view need also update masonry as well, if you change items size use layout() method, if you add or remove items use reloadItems() method
methods: {
toggle(item) {
item.isGigante = !item.isGigante;
Vue.nextTick(() => {
// DOM updated
this.msnry.layout();
});
},
add() {
this.items.push({
isGigante: false,
size: '' + widthClasses[Math.floor(Math.random() * widthClasses.length)] + ' ' + heightClasses[Math.floor(Math.random() * heightClasses.length)]
});
Vue.nextTick(() => {
// DOM updated
this.msnry.reloadItems();
this.msnry.layout();
});
}
}
Please note that those methods are called after vue has completed DOM update using Vue.nextTick function.
Here is a working fiddle.
I guess the vue-way of doing this is by using refs. Just assign a ref property to your html element inside the template and access it using the vm.$ref instance property inside the mounted callback.
A sample code may look like this:
<template>
<div class="grid" ref="grid">
<div class="grid-item"></div>
<div class="grid-item"></div>
<div class="grid-item"></div>
</div>
</template>
<script>
import Masonry from "masonry"; // or maybe use global scoped variable here
export default {
mounted: function(){
let $masonry = new Masonry(this.$refs.grid, {
// masonry options go in here
// see https://masonry.desandro.com/#initialize-with-vanilla-javascript
});
}
}
</script>
In Vue2, there is no such thing as a ready lifecycle hook. Instead, the mounted lifecycle hook is triggered once the instance is "ready" in the way you think of.
Reference: https://v2.vuejs.org/v2/guide/instance.html#Lifecycle-Diagram
It could be that the vertical stack just indicates that masonry is not working (It's hard to tell without a codepen/plunkr). #riyaz-ali has the right idea though.
you must call masonry inside mounted() event to make it work.
i am using this on my project (with imagesloaded) its work perfectly
massonryApply (container, context, selector) {
container = $(`#${container}`)
const $grid = container.imagesLoaded(function () {
$grid.masonry({
itemSelector: `.${selector}`,
percentPosition: true,
columnWidth: `.${selector}`
})
$grid.masonry('reloadItems')
})
}

Initialize rating plugin using angularjs variable

I am using this rating plugin (http://metroui.org.ua/rating.html) in angularjs to show rating in star. I tried to initialize the current rating when page loads.
data-score="3"
is working but this
data-score="{{userreviewRatings.rating}}"
is not working
<div id="rating-stars" class="large fg-white rating active" style="height: auto;" data-score="{{userreviewRatings.rating}}">
</div>
<form id="rating-form">
<input type="text" id="website-rating" ng-click="submitrating()" name="rating">
</form>
<script>
$(function(){
$("#rating-stars").rating({
static: false,
stars: 5,
showHint: true,
showScore: false,
click: function(value, rating){
rating.rate(value);
$('#website-rating').val(value);
$('#website-rating').trigger('click');
}
});
});
</script>
can someone please tell me how can i give rating using angular variable?
I don't it's good to use both angular and jquery. they are very different in thought.
if you really want to use both of them. you should use $scope.$digest()after
$scope.userreviewRatings.ratinghas changed.
or use
```
$scope.$apply(function () {
$(function () {
$("#rating-stars").rating({
static: false,
stars: 5,
showHint: true,
showScore: false,
click: function (value, rating) {
rating.rate(value);
$('#website-rating').val(value);
$('#website-rating').trigger('click');
}
});
});
})
```

Transitioning from a state containing an ng-grid object is not working

In my AngularJS app, I use ui-router for navigation and ng-grid to display data. Things work fine until I transition from a state containing a grid to any other state. This is the corresponding template:
<div ng-controller="MainUserController" class="container-fluid">
<div class="row">
<div class="col-xs-3">
<div class="gridStyle" ng-grid="gridOptions"></div>
</div>
</div>
</div>
When transitioning away from this state to any other state, I log the following error flow:
TypeError: Cannot read property 'off' of null
at HTMLDivElement.<anonymous> (http://127.0.0.1:9000/bower_components/ng-grid/build/ng-grid.debug.js:1008:31)
at HTMLDivElement.jQuery.event.dispatch (http://127.0.0.1:9000/bower_components/jquery/dist/jquery.js:4624:9)
at HTMLDivElement.elemData.handle (http://127.0.0.1:9000/bower_components/jquery/dist/jquery.js:4292:46)
at Object.jQuery.event.trigger (http://127.0.0.1:9000/bower_components/jquery/dist/jquery.js:4533:12)
at jQuery.fn.extend.triggerHandler (http://127.0.0.1:9000/bower_components/jquery/dist/jquery.js:5241:24)
at removePatch [as remove] (http://127.0.0.1:9000/bower_components/angular/angular.js:2213:21)
at Object.leave (http://127.0.0.1:9000/bower_components/angular/angular.js:4079:17)
at Object.leave (http://127.0.0.1:9000/bower_components/angular-ui-router/release/angular-ui-router.js:2668:49)
at cleanupLastView (http://127.0.0.1:9000/bower_components/angular-ui-router/release/angular-ui-router.js:2717:22)
at http://127.0.0.1:9000/bower_components/angular-ui-router/release/angular-ui-router.js:2739:13
Removing ng-grid="gridOptions" solves the problem hence why I am assuming my conflict arises between ui-router and ng-grid.
Any insights?
EDIT: this is how I declare gridOptions.
$scope.gridOptions = {
data: 'data',
plugins: [new ngGridFlexibleHeightPlugin()],
showSelectionCheckbox: true,
columnDefs: [{ field: 'username', displayName: 'Name', width: "**" },
{ field: 'email', displayName: 'Email', width: "**"}]
};
There's an open issue with this error regarding the conflict of ng-grid and ui-router and it seems that Herve Prot found a fix, I haven't tested it yet.
line 952 in build/ng-grid.js:
grid.$topPanel.on('$destroy', function() {
if(grid.$topPanel == null) // FIX ui-router
return;
grid.$topPanel.off('mousedown');
if (grid.config.enableColumnReordering) {
grid.$topPanel.off('drop');
}
grid.$topPanel = null;
});
I also found I needed to change the below (see Alex Choroshin post)
grid.$groupPanel.on('$destroy', function () {
if (grid.$groupPanel == null) // FIX ui-router
return;
grid.$groupPanel.off('mousedown');
grid.$groupPanel = null;
});
Its just a few lines above the recommended fix.
I solved changing the order of jQuery dependency in my dependencies on index.html before the ui-router dependency.

Categories