i need to show /hide buttons at specific ion view
and this buttons appearance depend on function
as my sample:
.controller('IntroCtrl', function ($scope, $state, $ionicSlideBoxDelegate) {
$scope.showalbums=false;
$scope.showalbums_new=true;
checkfolders();
if(hasalbums==1)
{
$scope.showalbums=true;
$scope.showalbums_new=false;
}
and in html page:
<i class="ion-images font-ion margin-right-8" ng-click="myAlbums()" ng-show="showalbums"></i>
<button class="button button-positive button-clear no-animation"
ng-click="showAlert2()" ng-if="slideIndex == 2" ng-show="showalbums_new" >
and my method in js:
var hasalbums=0;
function checkfolders()
{
window.requestFileSystem(LocalFileSystem.PERSISTENT, 0,
function(fileSystem){ // success get file system
directoryEntry = fileSystem.root;
if( !directoryEntry.isDirectory ) {
hasalbums=0;
}
currentDir = directoryEntry; // set current directory
directoryEntry.getParent(function(par){ // success get parent
parentDir = par; // set parent directory
}, function(error){ // error get parent
hasalbums=0;
});
var directoryReader = directoryEntry.createReader();
directoryReader.readEntries(function(entries){
alert(hasalbums);
if(entries.length>0)
{
hasalbums=1;
}else{
hasalbums=0;
}
}, function(error){
hasalbums=0;
});
}, function(evt){ // error get file system
hasalbums=0;
}
);
alert(hasalbums);
}
but method not called and can't show/hide buttons as i need
while this function is working correctly
In Ionic, controllers normally only load once. So we need to use ionic's lifecycle events to trigger some logic in your controller everytime you arrive at this view. Example:
.controller('IntroCtrl', function ($scope, $state, $ionicSlideBoxDelegate) {
$scope.$on('$ionicView.loaded', function () {
checkfolders();
});
Now your checkfolders() method will be executed everytime you arrive at this view, after your content has loaded. Refer this for other lifecycle events in ionic: http://ionicframework.com/docs/api/directive/ionView/
Related
I want to add a custom button on the Insert/Edit Link dialog/popup in tinymce v5.
I only got this code for the setup option where I put in call to a function.
function tinyMceEditLink(editor) {
console.log("tinyMceEditLink");
editor.on("click", function(e) {
console.log("this click");
});
}
I'll be the first to admit this is a bit hacky, but you could try:
function tinyMceEditLink(editor) {
editor.windowManager.oldOpen = editor.windowManager.open; // save for later
editor.windowManager.open = function (t, r) { // replace with our own function
var modal = this.oldOpen.apply(this, [t, r]); // call original
if (t.title === "Insert/Edit Link") {
$('.tox-dialog__footer-end').append(
'<button title="Custom button" type="button" data-alloy-tabstop="true" tabindex="-1" class="tox-button" id="custom_button">Custom button</button>'
);
$('#custom_button').on('click', function () {
//Replace this with your custom function
console.log('Running custom function')
});
}
return modal; // Template plugin is dependent on this return value
};
}
This will give you the following result:
Setup:
tinymce.init({
selector: "#mytextarea", // change this value according to your HTML
plugins: "link",
menubar: "insert",
toolbar: "link",
setup: function(editor) {
// Register our custom button callback function
editor.on('init',function(e) {
tinyMceEditLink(editor);
});
// Register some other event callbacks...
editor.on('click', function (e) {
console.log('Editor was clicked');
});
editor.on('keyup', function (e) {
console.log('Someone typed something');
});
}
});
Tips:
You can replace $('.tox-dialog__footer-end')... with $('.tox-dialog__footer-start')... if you want your button on the left hand side of the footer.
This currently works on the default skin, changes to .tox-dialog__footer class could break this.
Any updates to the library that change the title "Insert/Edit Link" will break this.
The above example requires jQuery to work.
This is a bare minimum example. Use the configuration guide to customize the toolbar, setup events etc.
I've a custom control which have multiple properties inserted in Detail View page. I've binded data with these properties. Scenario is I've two pages one is list view and then detail view. I've to navBack from detail page and select diff product from main page.Detail view page show diff products detail according to selected product. everything works fine. but problem is that my custom control doesn't update values and other page have updated values.
<custom:product topic="" subTopic="{product>name}" id="productDetial"></custom:product>
I've used one methond this.getView().byId("productDetail").rerender(); but it doesn't update my Inner HTML of control.
the control code. might be some typos error.as I've changed some variables name and remove unwanted code. the purpose is to show the methods which I've used and how I did
sap.ui.define([
"sap/m/Label",
"sap/m/Button",
"sap/m/CustomTile"
], function(Label, Button, CustomTile) {
"use strict";
jQuery.sap.declare("testProduct.control.product");
return CustomTile.extend("testProduct.control.product", {
metadata: { // the Control API
properties: {
name: {
type: "string",
defaultValue: "--"
},
subTopic: {
type: "string",
defaultValue: "--"
}
}
},
init: function() {
},
rerender: function(oRM, oControl) {
},
renderer: function(oRM, oControl) {
oRM.write('<div class=" sapMTile customTileCourseDetail">');
oRM.write('<div class="leftTileYourScore">');
if (oControl.getSubTopic() !== "" && oControl.getSubTopic() !== undefined) {
oRM.writeEscaped(oControl.getSubTopic());
} else {
oRM.write(" ");
}
oRM.write('</div>');
oRM.write('</div>
}
});
});
Yo just need to add a setter function in you control. When the binding is refreshed/changes, UI5 will trigger a setter method specific to the property. So in you case for the property subTopic it expects a method setSubTopic. This method should define you own logic to update said property in the UI layer according to your needs.
Here is part of the code you need to add, you will also have to tweak the initial rendering logic a bit.
renderer: function (oRM, oControl) {
//oRM.write('<div class=" sapMTile customTileCourseDetail">');
oRM.write("<div")
oRM.writeControlData(oControl);
oRM.addClass("sapMTile customTileCourseDetail");
oRM.writeClasses();
oRM.write(">");
oRM.write('<div class="leftTileYourScore">');
if (oControl.getSubTopic() !== "" && oControl.getSubTopic() !== undefined) {
oRM.writeEscaped(oControl.getSubTopic());
} else {
oRM.write(" ");
}
oRM.write('</div>');
oRM.write('</div>');
},
setSubTopic: function(sText){
this.setProperty("subTopic", sText, true);
$("#"+this.sId+" .leftTileYourScore").html(sText);
}
While navigating from one screen to another onExit has to be called to free resources. However it is not triggered. This is my code:
function (BaseController, JSONModel, formatter, Filter, FilterOperator) {
"use strict";
return BaseController.extend("app.controller.Worklist", {
_oCatalog: null,
_oResourceBundle: null,
onInit: function() {
this._oView = this.getView();
},
onThirdScreen : function (oEvent) {
this.getRouter().navTo("thirdscreen", {});
},
onExit: function() {
if (this._Dialog) {
this._Dialog.destroy(true);
}
}
});
});
As #mattbtt has mentioned, views are not destroyed each time you switch to another view so the "exit" event will not be triggered. What you can do, however, is to handle the onBeforeHide/onAfterHide events from the view instead.
onInit: function() {
this._oView = this.getView();
this._oView.addEventDelegate({
onBeforeHide: function(oEvent) {
debugger;
},
onAfterHide: function(oEvent) {
debugger;
}
}, this)
}
This is the expected behavior as navigating via the routing mechanism does not destroy the corresponding view. This makes a lot of sense as views normally do not change during the lifespan of their parent component. Furthermore it would slow down the application if views need to be repeatedly instantiated if the corresponding route matches.
In my app i have an XML view that consists of a smartform. I have a need to access an input element(via sap.ui.getCore().byId()) that becomes available after the smartform is parsed and rendered.
The onAfterRendering in the controller for my view triggers as soon as the view is rendered(i get all my non-smartform elements like title etc.), but before the smartform is parsed and rendered. A rudimentary test via an alert also proved this visually.
Is there any event that is triggered after the smartform has rendered which i can hook into to access my input element?
The developer guide walkthrough is extending the smartform and thus has its init method, but in my case i am extending the basecontroller and my init is for the page view.
Thanks for any pointers.
My View:
<mvc:View
controllerName="myns.controller.Add"
xmlns:mvc="sap.ui.core.mvc"
xmlns:semantic="sap.m.semantic"
xmlns:smartfield="sap.ui.comp.smartfield"
xmlns:smartform="sap.ui.comp.smartform"
xmlns="sap.m">
<semantic:FullscreenPage
id="page"
title="{i18n>addPageTitle}"
showNavButton="true"
navButtonPress="onNavBack">
<semantic:content>
<smartform:SmartForm
id="form"
editable="true"
title="{i18n>formTitle}"
class="sapUiResponsiveMargin" >
<smartform:Group
id="formGroup"
label="{i18n>formGroupLabel}">
<smartform:GroupElement>
<smartfield:SmartField
id="nameField"
value="{Name}" />
</smartform:GroupElement>
</smartform:Group>
</smartform:SmartForm>
</semantic:content>
<semantic:saveAction>
<semantic:SaveAction id="save" press="onSave"/>
</semantic:saveAction>
<semantic:cancelAction>
<semantic:CancelAction id="cancel" press="onCancel"/>
</semantic:cancelAction>
</semantic:FullscreenPage>
My Controller:
sap.ui.define([
"myns/controller/BaseController",
"sap/ui/core/routing/History",
"sap/m/MessageToast"
],function(BaseController, History, MessageToast){
"use strict";
return BaseController.extend("myns.controller.Add",{
onInit: function(){
this.getRouter().getRoute("add").attachPatternMatched(this._onRouteMatched, this);
},
onAfterRendering: function(){
//I tried my sap.ui.getCore().byId() here but does not work
//An alert shows me this triggers before the smartform is rendered but
//after all the other non-smartform elements have rendered
},
_onRouteMatched: function(){
// register for metadata loaded events
var oModel = this.getModel();
oModel.metadataLoaded().then(this._onMetadataLoaded.bind(this));
},
_onMetadataLoaded:function(){
//code here....
},
onNavBack: function(){
//code here....
}
});
});
You can look for when SmartForm is added to the DOM with DOMNodeInserted event of jQuery.
For this you can use it's id to identify the SmartForm has been added to the DOM.
Every UI5 element gets some prefix after it has been added to the DOM.
for e.g. __xmlview0--form.
So to make sure required form is added you can split the id of added element, then compare it with id which you have given.
Although it's not optimal solution, but you can try.
onAfterRendering: function() {
$(document).bind('DOMNodeInserted', function(event) {
var aId = $(event.target).attr("id").split("--");
var id = aId[aId.length - 1];
if (id) {
if (id == "form") {
// smart form fields are accessible here
$(document).unbind("DOMNodeInserted");
}
}
})
}
My final solution (for now and uses the accepted answer provided by #Dopedev):
(in controller for the nested view containing the smartform)
onAfterRendering: function() {
$(document).bind('DOMNodeInserted', function(event) {
var elem = $(event.target);
var aId = elem.attr("id").split("--");
var id = aId[aId.length - 1];
if (id) {
if (id == "nameField") {
elem.find("input").on({
focus: function(oEvent) {
//code here;
},
blur: function(oEvent) {
//code here;
}
});
/*
elem.find("input").get(0).attachBrowserEvent("focus", function(evt) {
//code here
}).attachBrowserEvent("blur", function(ev) {
//code here
});
*/
$(document).unbind("DOMNodeInserted");
}
}
});
}
Here is my code..If I remove close modal function,there is no effect. If I click any where outside the modal, the modal closes. But I need this close modal function as I need to set a flag in it for further use. How can I proceed further?
$scope.$on('$ionicView.afterEnter', function() {
$scope.openModal();
}
$ionicModal.fromTemplateUrl("settings/settingsModal.html", {
scope: $scope,
animation: 'slide-in-up'
}).then(function(modal) {
$scope.modal = modal;
});
$scope.openModal = function(){
$scope.modal.show();
}
$scope.closeModal = function(){
$scope.modal.hide();
};
}
There are a two ways of implementing modal in Ionic. One way is to add separate template and the other is to add it on top of the regular HTML file, inside script tags. First thing we need to do is to connect our modal to our controller using angular dependency injection. Then we need to create modal. We will pass in scope and add animation to our modal.
After that we are creating functions for opening, closing, destroying modal and the last two functions are place where we can write code that will be triggered if modal is hidden or removed. If you don't want to trigger any functionality when modal is removed or hidden you can delete the last two functions.
Controller's Code:
.controller('MyController', function($scope, $ionicModal) {
$ionicModal.fromTemplateUrl('my-modal.html', {
scope: $scope,
animation: 'slide-in-up'
}).then(function(modal) {
$scope.modal = modal;
});
$scope.openModal = function() {
$scope.modal.show();
};
$scope.closeModal = function() {
$scope.modal.hide();
};
//Cleanup the modal when we're done with it!
$scope.$on('$destroy', function() {
$scope.modal.remove();
});
// Execute action on hide modal
$scope.$on('modal.hidden', function() {
// Execute action
});
// Execute action on remove modal
$scope.$on('modal.removed', function() {
// Execute action
});
});
HTML Code :
<script id = "my-modal.html" type = "text/ng-template">
<ion-modal-view>
<ion-header-bar>
<h1 class = "title">Modal Title</h1>
</ion-header-bar>
<ion-content>
<button class = "button icon icon-left ion-ios-close-outline"
ng-click = "closeModal()">Close Modal</button>
</ion-content>
</ion-modal-view>
</script>
There are also other options for modal optimization. I already showed how to use scope and animation. The table below shows other options.
Modal options
The close modal function is meant for situations where you would like to close the modal manually. For example after a certain time it has been open or if something happens/the user does something for example presses a button.
There are ways of listening to when the modal is hidden/removed which will suit your situation and needs. For example:
// Execute action on hide modal
$scope.$on('modal.hidden', function() {
// Execute action
console.log('modal was hidden');
});
// Execute action on remove modal
$scope.$on('modal.removed', function() {
// Execute action
console.log('modal was removed');
});
With these you should be able to do what I understood you are wanting to do.
Straight from the documentation: http://ionicframework.com/docs/api/service/$ionicModal/