Ionic2 Popover Change Width - ionic-framework

I want to change the popover width of only 1 page.
I tried this:
I do not want to use this $popover-ios-width in variable.scss files
since it changes the width on all pages.

You can create a custom class for only this popover and pass it in the cssClass on it's options
let's say you have this:
.custom-popover {
width: 60%;
}
In your popover creation you'll just insert it as the cssClass on the options
const customPopOver = this.popover.create({ yourPopoverPage, yourData, { cssClass: 'custom-popover'}});
customPopOver.present();
Hope this helps :D

#gabriel-barreto's answer is totally fine. However, I guess it needs an additional consideration in other versions.
In Ionic 3.6 the custom class is added to the <ion-popover> element. In order to override the default width rule set in .popover-content class, your selector should be:
.custom-popover .popover-content {
width: 60%;
}

Add this below code in variables.scss. works for me in Ionic 4.
ion-popover {
.popover-wrapper {
.popover-content {
width: fit-content;
max-width: 300px;
}
}
}

I do not know if it will still suit you, I found the same problem, but modifying the global variable scss configuration did not help me because I used multiple PopoverControllers in the project the only way I managed to do it is the following:
Place the ion-content as a parent element and add the id attribute
Get Parent Items to the Main Container:
ionViewDidLoad() {
let element = document.getElementById('id')
let parent=element.parentElement
let parent2 = parent.parentElement //popover-content
parent2.parentElement.style['width'] = "92px"
}

Try this...
myPopOver = this.popovercontroller.create({ component: MyCustomComponent,
event:ev,
cssClass: 'my-custom-popover'
})
myPopOver.present();
add my-custom-popover class in global.css file.

const customPopOver = this.popover.create({ yourPopoverPage, yourData, { cssClass: 'custom-popover'}});
You need to create popover and add cssClass prop as on code above, then you can use 'custom-popover' class in variables.scss file like below.
.custom-popover {
.popover-wrapper {
.popover-content {
width: 465px;
}
}
}

Related

Make default Ionic alerts larger

I'm trying to make the default Ionic Alerts larger. I'm developing an app that needs to have easy touch points and the default alerts are too small for what I'm needing.
I've tried enlarging the font as well as expanding the width of the alerts but nothing seems to actually make the alerts larger.
Any easy/best ways to do this?
AlertController supports custom classes which could be placed in your component's scss file and there you can do necessary alterations.
For example in your component's ts file you can have this method that creates alert with reference to custom class "scaledAlert":
delete() {
let confirm = this.alertCtrl.create({
title: "Are You Sure?",
cssClass: "scaledAlert",
message: "this will remove image from your image gallery",
buttons: [
{
text: "Cancel",
handler: () => {
console.log("Canceled delete");
}
},
{
text: "Confirm",
handler: () => {
console.log("deleting...");
this.deleteImageFromGallery(this.image)
.then(res => {
console.log(res);
})
.catch(err => {
console.log(err);
});
this.viewCtrl.dismiss();
}
}
]
});
confirm.present();
}
Now in the scss file you add class to style as you need to scale the controller, such class goes after your page or component:
home-page {
.item {
min-height: 2rem; /* <- this can be whatever you need */
}
ion-label {
margin: 0px 0px 0px 0;
}
.item-content {
padding-top: 0px;
padding-bottom: 0px;
margin-top: -12px;
margin-bottom: -12px;
height: 50px;
}
}
.scaledAlert {
transform: scale(1.5);
}
Here I used just naive "scale" function which may require you to add some cross browser compatible versions of it. But you should achieve what you want with it (it worked in my app without issues).
Alternatively you can override default styles using saas variables: https://ionicframework.com/docs/api/components/alert/AlertController/#sass-variables
You will have to alter them in theme\variables.scss" which is located in your project's folder
See more here: https://ionicframework.com/docs/theming/overriding-ionic-variables/
And third option is indeed to check elements' style via devtool and attempt to override those classes. But I don't like that way, feels a bit more hacky.
Some of the styles for alert are not getting updated if written in component SCSS file. The styles need to be written in the global scss file.

Detect scrollHeight change with MutationObserver?

How can I detect when scrollHeight changes on a DOM element using MutationObserver? It's not an attribute and it isn't data either.
Background: I need to detect when a scrollbar appears on my content element, the overflow-y of which is set to auto. I figured that the instant the scrollbar appears the value of scrollHeight jumps from 0 to, say, 500, so the idea was to set up a MutationObserver to detect a change in this property.
What I've got so far:
HTML
<div class="body" #body>
CSS
.body {
overflow-y: auto;
}
TypeScript
export class MyWatchedContent implements AfterViewInit, OnDestroy {
#ViewChild('body', { read: ElementRef })
private body: ElementRef;
private observer: MutationObserver;
public ngAfterViewInit() {
this.observer = new MutationObserver(this.observerChanges);
this.observer.observe(this.body.nativeElement, {
attributes: true,
});
}
public ngOnDestroy() {
this.observer.disconnect();
}
private observerChanges(records: MutationRecord[], observer: MutationObserver) {
console.log('##### MUTATION');
records.forEach((_record) => {
console.log(_record);
});
}
}
If I, for example, change the background color in the developer window I can see the observer firing
MUTATION
my-content-watcher.component.ts?d0f4:233 MutationRecord {type: "attributes", target: div.body, addedNodes: NodeList(0), removedNodes: NodeList(0), previousSibling: null…}
If, however, I change the window size to make the scrollbar appear there's no mutation detected. Is this doable with MutationObserver at all and if so, how?
Here's the answer, for anyone still looking for the solution:
As of today, it's not possible to directly monitor scrollHeight changes of an element.
The MutationObserver detects changes in the DOM tree, which could indicate a scrollHeight change, but that's a wild guess.
The ResizeObserver detects changes in the outer height of an element, but not the scrollHeight (i.e. "inner" height).
There is no ScrollHeight-Observer (yet).
BUT the solution is very close:
The Solution
The ResizeObserver detects changes in the outer height of an element...
There's no point in observing the scroll-container because its outer height does not change. The element that changes their out height is any CHILD node of the container!
Once the height of a child node changes, it means, that the scrollHeight of the parent container changed.
Vanilla JS version
const container = document.querySelector('.scrollable-container');
const observer = new ResizeObserver(function() {
console.log('New scrollHeight', container.scrollHeight);
});
// This is the critical part: We observe the size of all children!
for (var i = 0; i < container.children.length; i++) {
observer.observe(container.children[i]);
})
jQuery version
const container = $('.scrollable-container');
const observer = new ResizeObserver(function() {
console.log('New scrollHeight', container[0].scrollHeight);
});
container.children().each(function(index, child) {
observer.observe(child);
});
Further steps
When children are added dynamically, you could add a MutationObserver to add new children to the ResizeObserver once they were added.
You can emulate this behavior by adding an internal wrapping element on the contenteditable element (eg a span) and then add the ResizeObserver listener on the internal element. The internal span has to be display:block otherwise it wont trigger the ResizeObserver.
HTML
<div contenteditable id="input"><span id="content">Some content</span></div>
CSS
#input {
max-height: 100px;
overflow: scroll;
white-space: pre-wrap;
}
#content {
display: block;
white-space: pre-wrap;
}
JS
const content = document.getElementById("content");
const observer = new ResizeObserver((entries) => {
for (const entry of entries) {
console.warn(entry);
}
});
observer.observe(content);

How to Set Width of sap.m.MessagePopover?

The control sap.m.MessagePopover has an attribute _oPopover (containing sap.m.Popover inside).
Using this attribute, I could set the popover width:
messagePopover._oPopover.setContentWidth("450px");
However, as SAP attributes starting from _ should not be used, does anybody know a cleaner way?
As of UI5 version 1.46, a more flexible control sap.m.MessageView can be used instead of the old sap.m.MessagePopover.
There is no need to access internal properties or apply custom CSS style classes to manipulate the width as you can put MessageView anywhere you want (Still, Fiori Guideline recommends to use it only within a responsive popover or a dialog).
const popover = new ResponsivePopover({
contentWidth: "450px",
contentHeight: "450px",
content: [
/*myMessageView*/
],
});
// ...
popover.openBy(...);
Compared to MessagePopover, MessageView can group items and more.
Internally, MessagePopover uses MessageView too.
Another solution would be to use CSS class. However, there is a catch. As you can see from below generated DOM of the message popover, inline styling has been used :( .
Only way to override inline-style is by using !important in CSS which is again not recommended approach. However, considering inline CSS has been used, I would go with using !important keyword. Below is the working code:
XML Code ( for adding Class):
<MessagePopover id='myMP' class='myPopoverClass'>
<items>
<MessagePopoverItem title='Title' subTitle='SubTitle'></MessagePopoverItem>
</items>
</MessagePopover>
CSS:
.myPopoverClass {
width:100rem;
}
.myPopoverClass .sapMPopoverCont {
width:100% !important;
}
You can play around with how much width you need for message Popover.
EDIT: This is from the source code:
MessagePopover.prototype.init = function () {
var that = this;
var oPopupControl;
this._oResourceBundle = sap.ui.getCore().getLibraryResourceBundle("sap.m");
this._oPopover = new ResponsivePopover(this.getId() + "-messagePopover", {
showHeader: false,
contentWidth: "440px",
placement: this.getPlacement(),
showCloseButton: false,
modal: false,
afterOpen: function (oEvent) {
that.fireAfterOpen({openBy: oEvent.getParameter("openBy")});
},
afterClose: function (oEvent) {
that._navContainer.backToTop();
that.fireAfterClose({openBy: oEvent.getParameter("openBy")});
},
beforeOpen: function (oEvent) {
that.fireBeforeOpen({openBy: oEvent.getParameter("openBy")});
},
beforeClose: function (oEvent) {
that.fireBeforeClose({openBy: oEvent.getParameter("openBy")});
}
}).addStyleClass(CSS_CLASS);

Can't set CSS to specified widget in GTK+

I'm using Vala with GTK+ and now I'm trying to add custom CSS to specified widget.
I can add fe. backgroudn to GtkWidget but not for #sidebar
#sidebar { //It doesn't work
color: white;
}
GtkWindow { // It works
background-color: red;
}
I'm adding class to widget like that:
sidebar = new Gtk.Label("Hello");
sidebar.set_name("sidebar");
And it's changes color to GtkWindow, but not for this label.
Any ideas?
I haven't programmed in Vala, but you should add class to StyleContext.
This is in C
sidebar = gtk_label_new ("Hello');
gtk_style_context_add_class ( gtk_widget_get_style_context ("mysidebar"), sidebar);
Also, style "sidebar", is already defined in GtkStyle. You should change the "sidebar" in CSS into something else (sidebar is used by views, toolbar etc)
But if you persist, the syntax should be:
.mysidebar {
#anything
}

DatePickers on the FloatPanel

I need to place several DatePicker widgets into the row. If there is not enough width to place all of them the rest widgets shift to the next row. It is the default HTML layout behavior. So I am trying to use FlowPanel. With any other widgets (Buttons, Labels, ...) everything ok, but DatePickers are placed one widget to the row. Here's the code
FlowPanel panel = new FlowPanel();
DatePicker picker1 = new DatePicker();
DatePicker picker2 = new DatePicker();
panel.add(picker1);
panel.add(picker2);
RootPanel.get().add(panel);
Any suggestions to solve this problem?
Thanks.
DatePicker's root element is a table so you'd have to give it a display: inline-table style, or put it in an element with display: inline-block style.
The following shouldn't break any other use of DatePicker, but won't work in IE 6 or 7; it's the Simplest Thing That Could Possibly Work™:
.gwt-DatePicker { display: inline-table; }
If you really need IE 6/7 support, you could try the following, in a CssResource:
#if user.agent ie6 {
.gwt-DatePicker { display: inline; }
}
#else {
.gwt-DatePicker { display: inline-table; }
}