fire directive after ng-repeat is finished - javascript

I am using owl carousel,for which data is coming from a ajax call. after ajax ng-repeat with populated the html content.
So i want to fire the directive which makes the owl carousel, after this all is done. How to do that.
One way i can think of using onFinishedRender directive, but this is not working.
directive :
directives.directive('onFinishRender',['$timeout', '$parse', function ($timeout, $parse) {
return {
restrict: 'A',
link: function (scope, element, attr) {
if (scope.$last === true) {
$timeout(function () {
scope.$emit('ngRepeatFinished');
if(!!attr.onFinishRender){
$parse(attr.onFinishRender);
}
});
}
}
}
}]);
controller:-
pastWorkService.getAllPastWork()
.success(function(data) {
var len = data.length;
$scope.pastWorkData1 = data.slice(0, len/2);
$scope.pastWorkData2 = data.slice(len/2, len - 1);
$scope.owlCarouselPastWork1 = function(){
$('.owl-carousel2').owlCarousel({
items: 4,
loop:true,
slideSpeed : 1000,
autoPlay: 3000,
itemsDesktop: [1199, 4],
itemsDesktopSmall: [980, 3],
itemsTablet: [768, 3],
itemsTabletSmall: false,
itemsMobile: [479, 1],
navigation: false
});
};
$scope.owlCarouselPastWork = function(){
$('.owl-carousel1').owlCarousel({
items: 4,
loop:true,
slideSpeed : 1000,
autoPlay: 3000,
itemsDesktop: [1199, 4],
itemsDesktopSmall: [980, 3],
itemsTablet: [768, 3],
itemsTabletSmall: false,
itemsMobile: [479, 1],
navigation: false
});
};
});
html:-
<div class="owl-carousel1" role="listbox" >
<div class="item" ng-repeat="p in pastWorkData1" on-finish-render="owlCarouselPastWork1()">
<img src="{{p.mainImage}}" alt="completed-projects" />
<div class="panel-footer">{{p.apartmentName}}</div>
</div>
</div>
<!-- second row goes here as owl carousel can contain 1 row -->
<div class="owl-carousel2" role="listbox" >
<div class="item" ng-repeat="p in pastWorkData2" on-finish-render="owlCarouselPastWork1()">
<img src="{{p.mainImage}}" alt="completed-projects" />
<div class="panel-footer">{{p.apartmentName}}</div>
</div>
</div>

Since you simply want to call a function after the last repeated item is rendered, here is one approach you could use:
html
<div class="owl-carousel1" role="listbox" >
<div class="item" ng-repeat="p in pastWorkData1">
<img src="{{p.mainImage}}" alt="completed-projects" />
<div class="panel-footer">{{p.apartmentName}}</div>
<span ng-if="$last" on-finish-render function-to-call="owlCarouselPastWork()"></span>
</div>
</div>
<!-- second row goes here as owl carousel can contain 1 row -->
<div class="owl-carousel2" role="listbox" >
<div class="item" ng-repeat="p in pastWorkData2">
<img src="{{p.mainImage}}" alt="completed-projects" />
<div class="panel-footer">{{p.apartmentName}}</div>
<span ng-if="$last" on-finish-render function-to-call="owlCarouselPastWork1()"></span>
</div>
</div>
directive
.directive('onFinishRender', function($timeout) {
return {
restrict: 'A',
scope: {
functionToCall: '&'
},
link: function(scope, elem, attrs) {
$timeout(function() {
scope.functionToCall();
});
}
}
})
Here is an extremely simple and contrived example to illustrate this idea. You could probably even rework this to have the function in the directive and you would simply pass the class identifier you want to call it on.

Related

ui-grid is blank when opening a bootstrap accordion a few seconds after the page loads?

So I'm currently attempting to dynamically create accordions which expand to a ui-grid containing some data. The issue is that if I do not expand the accordions within a few seconds of the page loading the ui-grid is blank. The outline of where the table should be exists but there is no data being displayed. I say being displayed because the data itself is in the html. It seems like its hidden by the accordion? When I resize the browser window the data appears though. Sorry if this is not detailed enough or I missed obvious debugging steps, I'm new to js/angular and to html. Below is my HTML code
<div ng-controller="TestController as test">
<script type="text/ng-template" id="group-template.html">
<div class="panel-heading">
<h4 class="panel-title" style="color:#fa39c3">
<a href tabindex="0" class="accordion-toggle" ng-click="toggleOpen()" uib-accordion-transclude="heading">
<span uib-accordion-header ng-class="{'text-muted': isDisabled}">
TEST
</span>
</a>
</h4>
</div>
<div class="panel-collapse collapse" uib-collapse="!isOpen">
<div class="panel-body" style="text-align: right" ng-transclude></div>
</div>
</script>
<uib-accordion close-others="oneAtATime">
<div ng-repeat="model in myData" track by $index>
<div uib-accordion-group class="panel-default" is-open="isOpen">
<uib-accordion-heading>
Test Model {{$index}} <i class="pull-right glyphicon" ng-class="{'glyphicon-chevron-down': isOpen, 'glyphicon-chevron-right': !isOpen}"></i>
</uib-accordion-heading>
<div id="grid[$index]" ui-grid="gridOptions[$index]" ui-grid-edit class="grid" style="clear:both"></div>
<br />
<strong>Last Cell Edited:</strong>{{msg[$index]}}<br />
<button>Commit Changes</button>
</div>
</div>
</uib-accordion>
and my angular
(function () {
var app = angular
.module('testApp', ['ui.grid', 'ui.grid.edit', 'ui.bootstrap', 'ngAnimate'])
.controller('TestController', TestController);
TestController.$inject = ['$scope', 'uiGridConstants'];
function TestController ($scope, uiGridConstants) {
$scope.oneAtATime = false;
$scope.myData = myData;
$scope.msg = [];
$scope.gridOptions = [];
$scope.getGridOptions = function (index) {
$scope.gridOptions[index] ={
showColumnFooter: true,
columnDefs: [
{ field: 'ticker', enableCellEdit: false, width: '33%' },
{ field: 'current_w', aggregationType: uiGridConstants.aggregationTypes.sum, enableCellEdit: false, width: '33%' },
{ field: 'new_w', aggregationType: uiGridConstants.aggregationTypes.sum, width: '33%' }
],
data: myData[index],
onRegisterApi: function (gridApi) {
$scope.gridApi = gridApi;
gridApi.edit.on.afterCellEdit($scope, function (rowEntity, colDef, newValue, oldValue) {
$scope.msg[index] = 'Edited Ticker:' + rowEntity.ticker + ' Column:' + colDef.name + ' newValue:' + newValue + ' oldValue:' + oldValue;
$scope.$apply();
})
}
}
};
for (i = 0; i < Object.keys($scope.myData).length; i++) {
$scope.getGridOptions(i);
console.log($scope.gridOptions[i]);
};
console.log($scope.gridOptions[1]);
};
var myData = [
[{ ticker: 'TICKER', current_w: 5, new_w: 4, },
{ ticker: 'TICKER 2', current_w: 3, new_w: 2, },
{ ticker: 'TICKER 3', current_w: 7, new_w: 0, }],
[{ ticker: 'TICKER', current_w: 5, new_w: 4, },
{ ticker: 'TICKER 2', current_w: 3, new_w: 2, },
{ ticker: 'TICKER 3', current_w: 7, new_w: 5, }]
];
})();
I would take a stab at this and say that you may want to add a ng-if="isOpen" to the ui-grid. So something like below should fix your problem.
<div id="grid[$index]" ui-grid="gridOptions[$index]" ui-grid-edit class="grid" style="clear:both" ng-if="isOpen"></div>
I was having issues with my grid displaying as well, and ensuring that the grid only appears when it is absolutely ready fixed the problem. The ui-grid documentation goes over this concept of a hidden grid at http://ui-grid.info/docs/#/tutorial/108_hidden_grids. They also have a plnkr that you can follow at http://plnkr.co/edit/LtpFnDUTofuxitb4Vh9x?p=preview. I hope this helps!

Ion-slide-box using button instead of swiping

I am trying to use a button in order to navigate through the slides however it does not work. I have done this so far:
HTML:
<ion-slide-box>
<ion-slide>
<button ng-click="slide()">Next</button>
</ion-slide>
<ion-slide>
This is the next slide
</ion-slide>
</ion-slide-box>
JS:
function controllerClass($scope, $ionicSlideBoxDelegate) {
$scope.slide = function() {
$ionicSlideBoxDelegate.next();
console.log("Click");
}
}
It shows the log "Click" but I don't know what is wrong with the slider itself.
I could really use help.
I have made a small demo for you
Plunker
HTML
<div class="button-bar">
<a ng-repeat="button in buttons" ng-class="{'active': $index === current}" ng-click="slide($index)" class="button button-stable">{{ button.name }}</a>
</div>
<ion-slide-box on-slide-changed="slideHasChanged($index)" slide-interval="1000" does-continue="true">
<ion-slide>
<div class="box" style="text-align:center;">
First slide
</div>
</ion-slide>
<ion-slide>
<ion-slide>
<div class="box" style="text-align:center;">
Second slide
</div>
</ion-slide>
</ion-slide>
</ion-slide-box>
Contoller
$scope.buttons = [{
name: '1'
}, {
name: '2'
}];
$scope.slide = function($index) {
$scope.current = $index;
$ionicSlideBoxDelegate.slide($index);
}
If you need any additional feature.Please let me know?
import { Component,ViewChild } from '#angular/core';
import { Slides } from 'ionic-angular';
#Component({ selector: 'page-calender', templateUrl: 'calender.html' })
export class CalenderPage {
#ViewChild(Slides) slides: Slides;
constructor() {}
gotoNextSlide() { this.slides.slideNext(); }
gotoPrevSlide() { this.slides.slidePrev(); }
}
Kind of a late answer, but I've been struggling with this component for a while.
You can also call the slider methods directly, when initialized, just store the slider object inside your controller and then use it:
The HTML:
<ion-slides
options="ctrl.slideOptions"
slider="ctrl.slider"
style="margin: -13px 0 0; height: 19.1em;">
<ion-slide-page
ng-repeat="b in ctrl.slideCollection"
ng-click="transCtrl.selectSlide(b)">
<!-- slide content here -->
</ion-slide-page>
<div class="swiper-button-next icon ion-chevron-right" ng-click="ctrl.slideNext($event)"></div>
<div class="swiper-button-prev icon ion-chevron-left" ng-click="ctrl.slidePrev($event)"></div>
</ion-slides>
And the JS:
ctrl.slideOptions = {
loop: true,
nextButton: '.swiper-button-next',
prevButton: '.swiper-button-prev',
pagination: false,
effect: 'coverflow',
coverflow: {
rotate: 50,
stretch: 0,
depth: 100,
modifier: 1,
slideShadows : false
}
};
$scope.$on("$ionicSlides.sliderInitialized", function(event, data){
// data.slider is the instance of Swiper
ctrl.slider = data.slider;
ctrl.activeIndex = 0;
});
$scope.$on("$ionicSlides.slideChangeStart", function(event, data){
console.log('Slide change is beginning');
});
$scope.$on("$ionicSlides.slideChangeEnd", function(event, data){
// note: the indexes are 0-based
ctrl.activeIndex = data.slider.activeIndex;
ctrl.previousIndex = data.slider.previousIndex;
});
ctrl.slideNext = function($event) {
ctrl.slider.onClickNext($event);
}
ctrl.slidePrev = function($event) {
ctrl.slider.onClickPrev($event);
}
The ng-click part is not always necessary, but if things do not work as expected it's nice to have a workaround.
I also have a tweak for the CSS buttons:
.swiper-button-next, .swiper-button-prev {
background: none;
}
Use it if you like Ionic icons better than the swiper ones (ugly blue caret...)

Loading Owl Carousel 2 with AngularJS dynamic content

I can't load owl carousel in a angularjs dynamic content.
I use this (edited) html:
<div id="Galeria" owlcarousel class="youplay-carousel gallery-popup">
<a class="angled-img" href="http://www.youtube.com/watch?v={{video}}" ng-repeat="video in juego.Galerias.Videos">
<div class="img">
<img src="http://img.youtube.com/vi/{{video}}/maxresdefault.jpg" alt="">
</div>
<i class="fa fa-play icon"></i>
</a>
<a class="angled-img" href="/img/galerias/{{imagen}}" ng-repeat="imagen in juego.Galerias.Imagenes">
<div class="img">
<img src="/img/galerias/{{imagen}}" alt="">
</div>
<i class="fa fa-search-plus icon"></i>
</a>
</div>
and this (edited) directive to my app:
app.directive('owlcarousel', function() {
var linker = function(scope, element, attr) {
var loadCarousel = function() {
console.log(element);
element.owlCarousel({
loop: !0,
stagePadding: 70,
nav: !0,
autoplay: 0 ? !0 : !1,
autoplayTimeout: 0,
autoplaySpeed: 600,
autoplayHoverPause: !0,
navText: ["", ""],
responsive: {
0: {
items: 1
},
500: {
items: 2
},
992: {
items: 3
},
1200: {
items: 4
}
}
});
}
scope.$watch("juego.Galerias.Videos", function(value) {
loadCarousel(element);
});
scope.$watch("juego.Galerias.Imagenes", function(value) {
loadCarousel(element);
})
}
return {
restrict: "A",
link: linker
}
});
But i can't load the carousel every time i load new content. I try to bind jquery event, call function in controller...etc.
PD: I use ng-routes and load html dinamically.
You can pass models to directive scope, and then do scope.$watch and reinit owlCarousel with reinit method. It is just an idea, if you could specify plunkr or fiddle it would be easier to help.

How to Convert ng-attr-id into id in Angular

I am using drag and drop library in Angular JS from the below link, its working perfectly because it doesn't have id in the div.
https://jasonturim.wordpress.com/2013/09/01/angularjs-drag-and-drop/
I am using HTML 5 drag and drop functionality but the problem I am facing to generate dynamic id of each via Angular J S. I have tried ng-attr-id and id both but I am not able to fetch the id of my element via angular.element(element l).a t tr("id").
Working Code
------------
HTML:
<div ng-controller="myCtl" style="margin-top :50 p x;">
<div class="row">
<div class="col-m d-1 col-m d-offset-1">
<p>Click and drag a color onto the grid to the right</p>
<div class="peg green" x-l v l-drag gable="true" data-color="green">Green</div>
<div class="peg red" x-l v l-drag gable="true" data-color="red">Red</div>
<div class="peg blue" x-l v l-drag gable="true" data-color="blue">Blue</div>
<div class="peg black" x-l v l-drag gable="true" data-color="black">Black</div>
<div class="peg grey" x-l v l-drag gable="true" data-color="grey">Grey</div>
</div>
<div class="col-m d-10">
<div n g-repeat="r in [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]">
<span class="slot circle" ng-repeat="c in [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]" x-l v l-drop-target="true" x-on-drop="dropped(drag E l, drop E l)"></span>
</div>
</div>
</div>
</div>
Controller( between the modal and view for drag and drop):
angular.module('my App', ['l v l. directives .drag drop'])
.controller('myCtl', ['$scope', function($scope) {
$scope.dropped = function(dragEl, dropEl) {
// this is your application logic, do whatever makes sense
var drag = angular.element(dragEl);
var drop = angular.element(dropEl);
console.log("The element " + drag.attr('id') + " has been dropped on " + drop.attr("id") + "!");
};
}]);
Modal(fetch the id of the dragged object ):
angular.element(element).at tr("id");
Not Working Code
----------------
HTML:
<div ng-controller="dd Controller" style="margin-top :50 p x;">
<div class="row">
<div class="col-m d-1 col-m d-offset-1">
<p>Click and drag a color onto the grid to the right</p>
<div ng-repeat="list in List">
<div id={{list.Name}} class="item" x-lvl-drag gable="true">{{list.Name}}</div>
</div>
</div>
<div class="col-m d-10">
<div n g-repeat="r in [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]">
<span class="slot circle" ng-repeat="c in [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]" x-l v l-drop-target="true" x-on-drop="dropped(drag E l, drop E l)"></span>
</div>
</div>
</div>
</div>
Controller( between the modal and view for drag and drop):
angular.module('my App', ['l v l. directives .drag drop'])
.controller('my C t l', ['$scope', function($scope) {
$scope.dropped = function(drag E l, drop E l) {
// this is your application logic, do whatever makes sense
var drag = angular.element(drag E l);
var drop = angular.element(drop E l);
console.log("The element " + drag. at tr('id') + " has been dropped on " + drop .at tr("id") + "!");
};
}]);
Modal(fetch the id of the dragged object ):
angular.element(element).at tr("id");
Access to the attributes in the "lvl-drag-drop.js" file is incorrect, if you are using a directive, you can access the attributes in the third argument.
link: function (scope, el, attrs, controller)
See the comments in this example:
module.directive('lvlDraggable', ['$rootScope', 'uuid', function($rootScope, uuid) {
return {
restrict: 'A',
link: function(scope, el, attrs, controller) {
//angular.element is no longer necessary if it refers to the element.
el.attr("draggable", "true");
//Incorrect
var id = angular.element(el).attr("id");
//This is correct
var id = attrs.id;
if (!id) {
id = uuid.new();
el.attr("id", id); //Also here
}
//.. more ...
}
}
}]);

angular: calling/triigering directive method from parent scope

in my app I defined a directive which implement a simple slider with a next/prev/goto methods.
The slider then is within an html snipet managed by another controller.
The problem is that the last slide contains a form, so if the submit is ok than I would like to go to the next slide.
In old javascript I would have passed a callback to the submit method in order to apply that callback.
I made the same thing. Is this the best / angular style way to do it?
Javascript (I omitted some detail):
.directive("sfCarousel", function() {
return {
scope: true,
restrict: 'A',
controller: function($scope) {
var slides = $scope.slides = [];
var currentIndex = $scope.currentIndex = -1;
$scope.next = function() {
//mynextfunction...
}
},
link: function(scope, element, attrs) {
console.log("sf-carousel");
}
}
})
.directive("sfCarouselItem", function() {
return {
scope: true,
require: '^sfCarousel',
link: function(scope, element, attrs, sfCarouselController) {
console.log("sf-carousel-item");
sfCarouselController.addSlide(scope);
}
}
})
.controller("mycontroller", ['$scope', function($scope) {
$scope.submit = function (callback) {
//if submit is ok then
callback.apply(null, []);
}
}])
HTML:
<div sf-carousel >
<div sf-carousel-item ng-class="{'active':active}" >
<div>my first slide</div>
<div sf-label="get-started.submit" ng-click="next()" ></div>
</div>
<div sf-carousel-item ng-class="{'active':active}" >
<form>
<!--here my form-->
<button type="submit" ng-click="submit(next)">submit and go</button>
</form>
</div>
<div sf-carousel-item ng-class="{'active':active}" >
<div>my last slide</div>
<!--other things-->
</div>
</div>
You can pass the function that you what to run on the parent controller.
// directive sfCarousel
return {
transclude: true,
template: '<div class="sf-carousel" ng-transclude></div>',
// ...
};
// directive sfCarouselItem
return {
transclude: true,
scope: {
func: '&',
// ...
},
template: '<div class="sf-carousel-item" ng-transclude></div>',
}
// controller html
<div sf-carousel >
<div sf-carousel-item ng-class="{'active':active}" >
<div>my first slide</div>
<div sf-label="get-started.submit" ng-click="next()" ></div>
</div>
<div sf-carousel-item func="next()" ng-class="{'active':active}" >
<form>
<!--here my form-->
<button type="submit" ng-click="func({})">submit and go</button>
</form>
</div>
<div sf-carousel-item ng-class="{'active':active}" >
<div>my last slide</div>
<!--other things-->
</div>
</div>

Categories