Scenario
I have a carousel in modal A which is made up of a bunch of slides. Each slide is a credit card. One of the slides however allows the user to launch modal B; this modal (Modal B) is used to record new credit card details. An object from modal B is then returned to A, after it's closed, which should then be added to the carousel in modal A.
Modal A
Modal B
Naturally I want this credit card (slide) to have the same functionality as the others, for example, if I click on it it should become the default credit card, highlighted by a grey background and a green tick on the top right.
I'm using slick-slider for the carousel and to add a new slide it needs a string so I'm trying to angularize my HTML string before adding it:
// Adds the new credit card
$scope.addNewCreditCard = function (newCreditCard) {
var slider = $('.slick-slider');
if (slider) {
var tempData = $scope.creditCardDetails;
$scope.creditCardDetails = null;
var htmlString = '<div class="creditcard" ng-click="fooBar()" '+
'<p>Some text</p>'+
'</div>';
// Angularize the string
var ngString = $compile(htmlString)($scope);
slider.slickAdd( ngString, 0, true);
// Update the object
$scope.creditCardDetails = tempData;
} else {
$log.error('Not found');
}
};
fooBar() is just a function that outputs an 'I've been clicked!' message to the console but it isn't being called when clicked.
Question
How do I go about compiling this string so it gets that function attached?
Thanks in advance
Note: This is not a directive, the modal, courtesy of angular bootstrap, is called like so:
$scope.showAddNewCreditCardModal = function () {
var modalInstance = $modal.open({
templateUrl: 'modules/common/partials/modals/addcreditcard/modal.addcreditcard.html',
backdrop: true,
windowClass: 'modal-add-credit-card',
controller: 'AddCreditCardCtrl',
size: 'lg',
scope: $scope
});
modalInstance.result.then(
function (success) {
// Below is a dummy that fills in the blanks for the card
var newCreditCard = {
'ElectronicPaymentAccountID': '123456789',
'ElectronicPaymentAccountType': 'ACP',
'CreditCardNumber': success.cardnumber,
'ExpirationDate': success.expmm + '/' + success.expyy,
'PreferredAccount': 'false',
'AccountName': ':o',
'PaymentTypeCode': ''
};
$scope.addNewCreditCard(newCreditCard);
},
function (error) {
$log.debug('Error: ' + JSON.stringify(error));
}
);
};
Before to answer your question, I want to get your attention on your condition:
var slider = $('.slick-slider');
if (slider) { ... }
I don't know if this is angular syntax but I think you should use this kind of condition:
var slider = $('.slick-slider');
if (typeof slider[0] != "undefined") { ... }
/* OR if (typeof slider[0] === "object") { ... } */
To answer, I don't really use AngularJS, but referring to "AngularJS + JQuery : How to get dynamic content working in angularjs", you maybe have to do something like:
var ngString.html($compile(htmlString)($scope));
I hope this informations help you.
Related
I have directive, essentially a button, that should only show on certain conditions. It uses addEventListener('scroll') to capture the scroll of a <ion-content> element in the containing page. This works fine for one page/view but when navigating to another page/view the scroll event is not fired?
'use strict';
angular.module('Fmpclient')
.directive('fmpRefreshButton', ['$window', '$ionicScrollDelegate', 'RefreshButtonService', function ($window, $ionicScrollDelegate, RefreshButtonService) {
var hideDelayTime = 3500;
var isButtonVisible = false;
var lastYPos = 0; // store the last Y Position
var timerId = null; // store a setTimeout id for later use
var $scrollEl = null;
var refreshButton = null;
/* __ code snipped for brevity __ */
/**
Work out the direction of scroll so we can
either hide or show the refresh button according to AC
#method onScroll
#public
*/
function onScroll () {
var scrollTop = $ionicScrollDelegate.getScrollPosition().top;
if(scrollTop > lastYPos) {
// Scrolling DOWN - hide refresh button
hideRefreshButton();
} else {
// Scrolling UP - show refresh button
shouldRefreshFeed();
}
// Store the last Y position to determine
// direction of scroll on next iteration
lastYPos = scrollTop;
}
/**
Setup directive elements on init
#method init
#public
*/
function init (){
console.log('directive::init()');
RefreshButtonService.setRefreshFeed(false);
$scrollEl = document.getElementById('ionContentScroll');
if($scrollEl){
$scrollEl.addEventListener('scroll', onScroll);
}
}
function _link(scope, element) {
refreshButton = element[0];
init();
}
return {
templateUrl: 'app/app/refresh-button/refresh-button.directive.html',
restrict: 'AE',
scope: true,
link: _link,
};
}
]);
As suggested by Scott, in the comment above, the solution to my rather trivial problem was to pass in the id as a parameter to the directive to ensure the id can be unique for each usage:
In the Directive scope:
scope: {
scrollElement: '='
},
and passed in on the Directive template:
<my-directive scroll-element="ionFeedScroll">
I have a list of elements. Ever element has a gallery attached to it.
I use a modal to show the gallery of each. It s working perfectly.
Now the problem I have is about the pictures that are showed first.
Let s say I have this in the first element :
Gallery
-JrYz8TI7N9ItkAoVtUZ
-JrYz8TJatqcBm-MBXIK
-JrYz8TJatqcBm-MBXIL
-JrYz8TLYhbKEnVEYmBC
and this in the second element
Gallery
-JrYz8sPnCEYM-TXHJ9I
-JrYz8sSLq_mJ6k_tSfG
I would like to always start showing the elements from the first element.
This does not ahppen here. I somhow end up having an index of 3 in a Gallery of 2 elements..
Can you tell me how I can change this behaviour?
Here is my modal ctroller:
// Dealing with modals for the gallery
$ionicModal.fromTemplateUrl('Cards/image-modal.html', {
scope: $scope,
animation: 'slide-in-up'
}).then(function(modal) {
$scope.modal = modal;
});
$scope.openModal = function(index) {
$scope.currentGallery = $scope.cards[index].Gallery;
//console.log('This is' + $scope.cards[index].Gallery);
console.log("When slide opens " + $scope.slideIndex);
$scope.modal.show();
// Important: This line is needed to update the current ion-slide's width
// Try commenting this line, click the button and see what happens
$ionicSlideBoxDelegate.update();
};
$scope.closeModal = function() {
console.log("When slide closes " + $scope.slideIndex);
$scope.slideIndex = 0;
console.log("When slide closes and I change it to " + $scope.slideIndex);
$scope.modal.hide();
};
// Cleanup the modal when we're done with it!
$scope.$on('$destroy', function() {
$scope.modal.remove();
console.log('Modal is destroyed!');
});
// Execute action on hide modal
$scope.$on('modal.hide', function() {
// Execute action
console.log('Modal is hidden!');
});
// Execute action on remove modal
$scope.$on('modal.removed', function() {
// Execute action
console.log('Modal is removed!');
});
$scope.$on('modal.shown', function() {
console.log("When slide is on MODAL.SHOW " + $scope.slideIndex);
console.log('Modal is shown!');
});
// Call this functions if you need to manually control the slides
$scope.next = function() {
$ionicSlideBoxDelegate.next();
};
$scope.previous = function() {
$ionicSlideBoxDelegate.previous();
};
// Called each time the slide changes
$scope.slideChanged = function(index) {
$scope.slideIndex = index;
console.log("When slide changes " + $scope.slideIndex);
};
here is my modal code:
<div class="modal image-modal transparent" ng-click="closeModal()">
<ion-slide-box on-slide-changed="slideChanged(index)" show-pager="false">
<ion-slide ng-repeat="item in currentGallery">
<img ng-src="{{item.picture}}" class="fullscreen-image" />
<p class="info">{{item.caption}}</p>
</ion-slide>
</ion-slide-box>
</div>
Can you please help?
I tried to change that index ay many places, and I do but it does not affect the slideshow moving forward..
Thank you in advance,
And cheers!
It has been solved... I basically used this :
var II = $ionicSlideBoxDelegate.currentIndex() + 1;
for (var i = II - 1; i >= 0; i--) {
$ionicSlideBoxDelegate.previous();
if ($ionicSlideBoxDelegate.previous() == 0) {
break;
};
};
This way, it always goes back to the beginning whenever I close it. Cheers!
I am not very familiar with the CKEDITOR API yet and now I got stuck trying to find the way to create placeholders inside of the CKEDITOR editable area.The expected behaviour for the placeholder - to dissappear on user interaction with it, allowing to edit the content instead.
I know that there is already a placeholder plugin (http://ckeditor.com/addon/placeholder) but its behaviour is not what I am looking for.
To be more specific, the question is: is it possible to subscribe for some events on the particular element inside of the CKEDITOR?
Working in the angular context I am able to compile my html before it is passed to the CKEDITOR ng-model
$scope.html = $compile('<div><span text-placeholder >Placeholder</span></div>')($scope).html();
But then I fail trying to set click events inside of the directive:
.directive('textPlaceholder', [ function () {
return {
restrict: 'A',
link: function ($scope, $element) {
//THIS DOES NOT WORK UNFORTUNATELY
$element.on('click', function () {
console.log('clicked');
})
}
}
}])
Any thoughts?
UPDATE: For now I came up with the solution to implement simple plugin and then reference it in the CKEDITOR config:
(function () {
CKEDITOR.plugins.add('text-placeholder', {
init: function (editor) {
editor.on('key', function (evt) {
var el = $(CKEDITOR.instances.editor1.getSelection().getNative().baseNode.parentElement);
if (el.hasClass('text-placeholder')) {
el.remove();
}
});
}
});
})();
Looks ugly for me. Any feedback is appreciated.
This seems to be a final Solution:
CKEDITOR.plugins.add('text-placeholder', {
init: function (editor) {
editor.on('contentDom', function () {
var editable = editor.editable();
editable.attachListener(editable, 'click', function (event) {
var $placeholder = $(event.data.$.target).closest('.text-placeholder');
if ($placeholder.length > 0) {
var selection = editor.getSelection();
selection.selectElement(selection.getStartElement());
}
});
});
}
});
This applies the selection on the element with "text-placeholder" class when user focuses it inside of the editable area
Update:
See example
You inspired me to write one myself, using the above example as a starting point. In my use case I wanted to take placeholder text from an attribute on the editor -- data-placeholder -- and display it in the editor. When the editor gets focus, the placeholder text disappears. When the editor blurs -- if no user content has been entered -- the placeholder text is displayed again. Additionally, I set a data-placeholder-showing attribute so that I can, for example, use CSS to make the placeholder text gray. Here's my code:
CKEDITOR.plugins.add('text-placeholder', {
init: function (editor) {
var placeholder = editor.element.getAttribute('data-placeholder');
editor.on('contentDom', function () {
if (placeholder) {
editor.setData(placeholder);
editor.element.setAttribute('data-placeholder-showing', true);
}
});
editor.on('focus', function() {
if (editor.getData() === placeholder) {
editor.element.setAttribute('data-placeholder-showing', false);
editor.setData('');
}
});
editor.on('blur', function() {
if (placeholder && editor.getData().length === 0) {
editor.element.setAttribute('data-placeholder-showing', true);
editor.setData(placeholder);
}
});
}
});
I have a list that looks like this:
Store 1
Section A
Section B
and so on...
Store 2
Section A
and so on...
So I open a modal window to create a new store. I return the store when I close the window, and so far that's working great!
<div ng-repeat="store in global.user.company2.store">
I need to push the callback store to $scope.global.user.company2.store[?]
modalInstance.result.then(function (newStore) {
// How do I get the IndexOf value of store?
// This is one of the stores in the ng-repeat
$scope.global.user.company2.store[???].section.push(newStore)
}, function () {
$log.info('Modal dismissed at: ' + new Date());
});
The way I'm sending a selected store into the modal is with resolve
$scope.createSection = function (size) {
var modalInstance = $modal.open({
templateUrl: 'createSection.html',
controller: 'SectionModal',
size: size,
resolve: {
items: function () {
// $scope.radio.model === store
// $scope.radio.model2 === section
return $scope.radio;
}
}
});
UPDATE: Here's a basic plunker http://plnkr.co/edit/UGN4niAO9nQETqhg8lxn
The radio model buttons aren't working. If you change resolve items to $scope.radio.model, the modal breaks. So I left it as is. I think maybe it has to do with the btn-radio being part of angular-ui-bootstrap?
When resolving your modal, box your returned object with the array index of the object.
For example:
$modalInstance.close({ radio: $scope.radio, index: $scope.items.indexOf($scope.radio) } );
Then, when resolving your modal's promise, simply unbox your object:
modalInstance.result.then(function (selectedItem) {
$scope.selected = selectedItem.radio;
$scope.selectedIndex = selectedItem.index;
}, function () {});
See the Angular-Bootstrap docs for more details.
I am building a small message system. I use tabs in my state (inbox, outbox). Also, i want to sent a message when i click a "contact" link. If i click that link, this should happen:
change state to messages state
open other tab, called "newmsg"
At this moment, this is what i have:
<a ng-click="mailContact()">contact</a>
and i my controller:
$scope.mailContact = function() {
$state.go('root.messages');
$scope.openTab('new');
};
Obviously this is not working, because $scope.openTab('new'); will never execute. The state changes to what i want, but the tab is not opened. I do not have a clue of how to get it done.
Ok, stupid thing was i had an init which opened the "inbox"...
Now i wrote a service which does the trick.
app.factory('msgTabService', ['$rootScope', function($rootScope) {
var msgTabService = {};
var tabname = "inbox";
msgTabService.set = function(tab) {
tabname = tab;
};
msgTabService.get = function() {
return tabname;
};
msgTabService.openTab = function(tab) {
if ($rootScope.currenttab !== tab)
{
$rootScope.currenttab = tab;
msgTabService.set(tab);
}
};
return msgTabService;
}]);
The question may be similar to: Save State of Tab content when changing Route with angularjs and BootStrap Tabs