Why does the iOS content go up when a element is added? - ios

I'm using Ionic to build a chat app, but I'm facing a problem, when I run my app on the iOS environment, every time a new message is added to the content the content goes up without any reason.
I've tried everything but I still didn't find a way to fix it, note that this bug only appears with the iOS content but works perfectly on Android.
I've published a video to show this bug
here is the code that I'm using to update the messages
ngOnInit() {
this.chatID = this.route.snapshot.paramMap.get('id');
this.afs
.collection(`chat/${this.chatID}/messages`,(ref) => ref.orderBy('createdAt'))
.valueChanges({ idField: 'id' })
.subscribe((event) => {
this.data = event;
console.log(this.data);
});
}
This is the function to push the new message
addChatMessage() {
const { newMsg } = this;
this.chatID = this.route.snapshot.paramMap.get('id');
this.afs
.collection(`chat/${this.chatID}/messages`)
.add({
msg: newMsg,
profilePic: this.profilePic,
username: this.username,
from: this.user.getUID(),
createdAt: firebase.firestore.FieldValue.serverTimestamp(),
})
this.newMsg = '';
}
And here is the HTML code
<div *ngFor="let message of data">
<div style="display: flex; justify-content: flex-end">
<div style=" display: flex;
flex-direction: column;
align-items: flex-end;
">
<ion-card class="my-message"
*ngIf="message.username == username">
<ion-label>
{{ message.msg }}
<br />
</ion-label>
</ion-card>
</div>
</div>

Related

Angular Material Dialog with Google Places Autocomplete dropdown positioning

I have a web page that uses the Angular framework and therefore the Materials UI library. I have a dialog with a form that uses the Google Places Autocomplete functionality, but the positioning of it stays constant when scrolling through the dialog. Without the dialog, the autocomplete positioning works as I would like and stays directly beneath the input. No styling on the .pac-container has been done for the positioning. The dialog and non-dialog have the same code and styling. Thank you in advance! (Mind the ugliness, it is all testing right now)
google.maps.places.Autocomplete position offset inside angular material Dialog is the exact issue I am having (I think), but I do not know what is meant by "My solution was to remove the top style and then restore it."
Initial position of autocomplete in the dialog
Autocomplete position when scrolling through the dialog
Initial position of autocomplete outside dialog
Autocomplete position when scrolling outside dialog
Non-Dialog TS:
export class AddressTestComponent implements OnInit, AfterViewInit {
#ViewChild("addressLine1") addressField1: ElementRef;
#ViewChild("addressLine2") addressField2: ElementRef;
#ViewChild(MatAutocompleteTrigger, {static: false}) trigger: MatAutocompleteTrigger;
addressForm: UntypedFormGroup;
googleAutocomplete: google.maps.places.Autocomplete;
constructor(private formBuilder: UntypedFormBuilder) { }
ngOnInit(): void {
this.addressForm = this.formBuilder.group(
{
addressLine1: ['', Validators.required],
addressLine2: [''],
city: ['', Validators.required],
state: ['', Validators.required],
zipCode: ['', Validators.required],
country: ['', Validators.required],
}
);
}
ngAfterViewInit(): void {
this.googleAutocomplete = new google.maps.places.Autocomplete(this.addressField1.nativeElement as HTMLInputElement, {
componentRestrictions: { country: ["us"] },
fields: ["address_components"],
types: ["address"]
});
this.addressField1.nativeElement.focus();
this.googleAutocomplete.addListener("place_changed", () => this.autocomplete(this.googleAutocomplete.getPlace()) );
}
}
Non-Dialog HTML:
<div>
<div class="dialog-header">
<h2>Add a New Address</h2>
<h2 class="header-closer" (click)="onClose()" >X</h2>
</div>
<form [formGroup]="addressForm" (ngSubmit)="onSubmitNewAddress()" class="address-form">
<div class="address-wrapper">
<mat-form-field (keydown.escape)="$event.stopPropagation()"
appearance="fill">
<mat-label>Address Line 1</mat-label>
<input matInput #addressLine1 formControlName="addressLine1" required>
</mat-form-field>
<mat-form-field appearance="fill">
<mat-label>Address Line 2 (Optional)</mat-label>
<input matInput #addressLine2 formControlName="addressLine2">
</mat-form-field>
<mat-form-field appearance="fill">
<mat-label>City</mat-label>
<input matInput formControlName="city" required>
</mat-form-field>
<mat-form-field appearance="fill">
<mat-label>State</mat-label>
<input matInput formControlName="state" required>
</mat-form-field>
<mat-form-field appearance="fill" style="margin-bottom: 10px;">
<mat-label>Zip Code</mat-label>
<mat-hint align="end">{{ zipcode.value.length }} / 5</mat-hint>
<input matInput #zipcode type="tel" [maxLength]="5" formControlName="zipCode" required>
</mat-form-field>
<mat-form-field appearance="fill">
<mat-label>Country</mat-label>
<input matInput formControlName="country" required>
</mat-form-field>
</div>
<div class="form-buttons">
<button mat-raised-button (click)="onClose()">Cancel</button>
<button mat-raised-button color="primary" type="submit" [disabled]="this.addressForm.invalid">Use This Address</button>
</div>
</form>
</div>
Non-Dialog SCSS:
.dialog-header {
display: flex;
justify-content: space-between;
align-items: baseline;
margin-bottom: 5px;
}
#map {
height: 100%;
}
.address-form {
padding-bottom: 2000px; // for scrolling test
}
.header-closer {
cursor: pointer;
color: red;
margin-top: 30px;
}
.address-wrapper {
display: flex;
flex-wrap: wrap;
mat-form-field {
margin: 0 15px;
flex: 1;
}
}
.form-buttons {
button {
margin: 0 5px;
}
button:hover {
background-color: #771f1f;
}
}
I have tried the autocomplete without a Material Dialog and it works just as intended and how I would like it to work. I am just trying to replicate that while scrolling through the dialog as well. To fix the issue, I tried to change the position styling of .pac-container but was unsuccessful.
EDIT: I figured out what the other stackoverflow link was talking about. Is there a way the autocomplete styling can be tied to the actual input element rather than the html tag?

mat-radio-button doesn't work properly when mat-dialog direction is RTL

My question is how could I use the mat-radio-button inside RTL mat-dialog?
Here are the details:
When I changed the Mat Dialog configuration to RTL such below :
private showCreateOrEditDialog(id?: number): void {
const dialogConfig = new MatDialogConfig();
dialogConfig.width="100%";
dialogConfig.height="100%";
dialogConfig.maxWidth='100vw';
dialogConfig.maxHeight='100vh';
dialogConfig.disableClose=true;
dialogConfig.direction="rtl"; //<========= if I change it to ltr everything // working fine
let createOrEditDialog;
if (id === undefined || id <= 0) {
createOrEditDialog = this._dialog.open(CreateComponent,dialogConfig);
} else {
createOrEditDialog = this._dialog.open(EditComponent, {
data: id
});
}
createOrEditDialog.afterClosed().subscribe(result => {
// if (result) {
// this.rerender(Number(this.selecteddCity));
// }
});
}
the mat-radio-button stop working properly :
1- first thing the scroll-x extended to much such below screen shoot.
this problem disappeared when removing the mat-radio-buttons from my form
2- second thing I can't select any one of them, both mat-radio-button not selected but when my form was in LTR I were could choose one of them but in RTL direction I cant.
here is my angular :
<form autocomplete="off" #createModal="ngForm" (ngSubmit)="save()">
<h1 mat-dialog-title>Create New </h1>
<mat-dialog-content style="width: 100%;height:100%;">
<mat-tab-group>
<mat-tab [label]="'GeneralInformation' | localize">
<div class="row">
<div class="col-md-4" >
<mat-form-field >
<mat-radio-group aria-label="Select an option" labelPosition="before" name='Readiness' required>
<mat-radio-button class='Readiness' [value]="1" >ready</mat-radio-button>
<mat-radio-button class='Readiness' [value]="0" >not ready</mat-radio-button>
</mat-radio-group>
<label id="Readiness-ID">Readiness</label>
</mat-form-field>
</div>
</div>
</mat-tab>
</mat-tab-group>
</mat-dialog-content>
<div mat-dialog-actions align="end">
<button mat-button type="button" [disabled]="saving" (click)="close(false)">
{{ "Cancel" | localize }}
</button>
<button
mat-flat-button
type="submit"
flex="15"
color="primary"
[disabled]="!createModal.form.valid || saving">
Save
</button>
</div>
</form>
I got it . its a weird problem but when I check the materialize.css file I found below CSS tags :
[type="radio"]:not(:checked),
[type="radio"]:checked {
position: absolute;
left: -9999px;
opacity: 0;
}
What I did simply I commented them and every thing working fine !
/* Radio Buttons
========================================================================== */
/* [type="radio"]:not(:checked),
[type="radio"]:checked {
position: absolute;
left: -9999px;
opacity: 0;
} */
Update:
Similar problem for Checkboxes,so, you should comment below css in materialize.css file :
/* [type="checkbox"]:not(:checked),
[type="checkbox"]:checked {
position: absolute;
left: -9999px;
opacity: 0;
} */
Note: materialize version is Materialize v0.97.7 (http://materializecss.com)

md-datepicker width is too big

I'm stuck to customize size of md-datepicker! I use it in md-input-container but the size after the picker is shown up ,it takes all my screen size.Below is my code:
<md-input-container flex-xs>
<label>Start Date</label>
<md-datepicker ng-model="leave.start_date"></md-datepicker>
</md-input-container>
Do I need to include any original styles of this datepicker? Thank in advance!
Use the function for manipulate width and hide image of calendar as:
var app = angular.module('StarterApp', ['ngMaterial']);
app.controller('AppController', function($scope) {
$scope.initDatepicker = function(){
angular.element(".md-datepicker-button").each(function(){
var el = this;
var ip = angular.element(el).parent().find("input").bind('click', function(e){
angular.element(el).click();
});
angular.element(this).css('visibility', 'hidden');
});
};
});
CSS
This comes from how the date picker is build behind the scene
.inputdemoBasicUsage .md-datepicker-button {
width: 36px;
}
.inputdemoBasicUsage .md-datepicker-input-container {
margin-left: 2px;
}
.md-datepicker-input-container {
display: block;
}
.md-datepicker-input[placeholder] {
color:red;
}
.padding-top-0 {
padding-top: 0px;
}
.padding-bottom-0 {
padding-bottom: 0px;
}
HTML
<div ng-app="StarterApp" ng-controller="AppController" ng-init="initDatepicker();">
<md-content flex class="padding-top-0 padding-bottom-0" layout="row">
<md-datepicker ng-model="user.submissionDate1" md-placeholder="Start date" flex ng-click="ctrl.openCalendarPane($event)"></md-datepicker>
<md-datepicker ng-model="user.submissionDate2" md-placeholder="Due date" flex></md-datepicker>
</md-content>
</div>

Ionic Framework textarea keyboard scroll issue after Apple Testflight processing

We are using the ionic framework with iOS.
In the iOS emulator and in Safari browser, for one of our pages, clicking in a textarea shows the keyboard, and scrolls the textarea upwards so it is still viewable.
When the app is archived and processed through Apple iOS TestFlight, the behaviour is changed. Now, clicking in a textarea shows the keyboard, but the textarea no longer scrolls upwards so it is hidden.
Looks like something in the archival process is causing an issue.
Here's the code (there's another div above it). There's only the one textarea.
<div ng-if="!dy_compl">
<div class="wi-bottom item ">
<div ng-repeat="(key, dy) in element.dys">
<div id="wi-scroll-div" ng-if="key == dySel" style="height: {{scroller_height}}; overflow: scroll;">
<div>
<style>
p.wi-icon:before {
background: url("img/old_building.png") no-repeat !important;
}
</style>
<p class="wi-icon" ng-bind-html="dy.intro | to_trusted"></p>
</div>
<div ng-if="dy.ref">
<p class="wi-intro-my3" ng-bind-html="dy.ref.intro | to_trusted"></p>
<div ng-repeat="data in dy.ref.data track by $index">
<p class="wi-intro-my3-table" style="margin-left: 5%;" ng-bind-html="data | to_trusted"></p>
</div>
</div>
<label id="wi-input" class="item item-input item-stacked-label">
<span class="input-label" style="width:100%; max-width: 100%;">
<div class="wi-bottom-input-label" ng-bind-html="dy.notelabel | to_trusted"></div>
</span>
<textarea class="wi-bottom-input" ng-model="dy.note" type="text" placeholder="{{dy.note}}" ng-style="{'background-color': textAreaBackgroundColor}"></textarea>
</label>
<button class="wi-bottom-button button button-assertive col text-center" ng-click="dy.saved=true;saveNow()">
Save Notes
</button>
</br>
</div>
</div>
</div>
If you can't make it work with the plugin, check out this code I used on one project.. Looks a bit overhead, but it works:
Template:
<ion-content scroll-handle="user-profile-scroll">
<textarea maxlength="160" ng-model="currentUser.bio" ng-readonly="!editMode || focusAddInterestInput" placeholder="Write your bio..." class="user-bio">< </textarea>
</ion-content>
Controller:
$scope.windowHeight = window.innerHeight;
$scope.keyboardHeight = 0;
$scope.$on('$ionicView.loaded', function() {
var scrollView = {scrollTo: function() { console.log('Could not resolve scroll delegate handle'); }};
$timeout(function() {
var instances = $ionicScrollDelegate.$getByHandle('user-profile-scroll')._instances;
instances.length && (scrollView = instances[instances.length - 1]);
}).then(function() {
$scope.unbindShowKeyboardHandler = $scope.$on('KeyboardWillShowNotification', function(evt, info) {
$scope.keyboardHeight = info.keyboardHeight;
var input = angular.element(document.activeElement);
var body = angular.element(document.body);
var top = input.prop('offsetTop');
var temp = angular.element(input.prop('offsetParent'));
var tempY = 0;
while (temp && typeof(temp.prop('offsetTop')) !== 'undefined') {
tempY = temp.prop('offsetTop');
top += tempY;
temp = angular.element(temp.prop('offsetParent'));
}
top = top - (scrollView.getScrollPosition().top || 0);
var inputHeight = input.prop('offsetHeight');
var requiredSroll = $scope.windowHeight - $scope.keyboardHeight > top + inputHeight + 11 ? 0 : $scope.windowHeight - $scope.keyboardHeight - top - inputHeight - 12;
$timeout(function(){ scrollView.scrollTo(0, - requiredSroll || 0, true); });
});
$scope.unbindHideKeyboardHandler = $scope.$on('KeyboardWillHideNotification', function(evt, info) {
console.log(evt, info);
$scope.keyboardHeight = 0;
$timeout(function() { scrollView.scrollTo(0, 0, true); });
});
$scope.$on('$destroy', function() {
$scope.unbindShowKeyboardHandler();
$scope.unbindHideKeyboardHandler();
});
});
});
andm finally in app.js:
window.addEventListener('native.keyboardshow', keyboardShowHandler);
window.addEventListener('native.keyboardhide', keyboardHideHandler);
function keyboardShowHandler(info){
$rootScope.$broadcast('KeyboardWillShowNotification', info);
}
function keyboardHideHandler(info){
$rootScope.$broadcast('KeyboardWillHideNotification', info);
}
Turns out that we had one view that was manually disabling the keyboard scroll using:
cordova.plugins.Keyboard.disableScroll(true)
We weren't re-enabling this on a switch to another view.
The result is that in the emulator, the scroll disabling didn't traverse the scope to the new page, whereas after archival and TestFlight, it did.
Thanks for the other answers, comments.

Modal box "hidden" behind greyed out area

Im following along with http://multiplethreads.wordpress.com/tag/pagedown/
The example in the link above makes use of twitter bootstrap whereas i make use of zurb foundation.
Basically im trying to get a custom dialog box to insert images from my pagedown editior (sort of like how stackoverflow does it).
Im abale to pull up the modal box (foundation reveal) but it seems to be "behind" something and i cant seem to interact with it. Any ideas?
My code:
js file:
PH.ui.markdown = {
initialize: function () {
var markdownTextArea = $('textarea[data-markdown=true]');
if (markdownTextArea.length == 1) {
markdownTextArea.addClass('wmd-input')
.wrap("<div class='wmd-panel' />")
.before("<div id='wmd-button-bar'></div>")
.after("<div id='wmd-preview' class='wmd-preview'></div>");
var converter = Markdown.getSanitizingConverter();
var editor = new Markdown.Editor(converter);
editor.hooks.set("insertImageDialog", function (callback) {
//setTimeout(function () {
$('#myModal').foundation('reveal', 'open');
// }, 5000);
return true; // tell the editor that we'll take care of getting the image url
});
editor.run();
}
}
};
html:
<div id="myModal" class="reveal-modal">
<h2>Upload Image</h2>
<%= f.file_field :image %>
<button class="btn" id="insert_image_post">Insert Image</button>
<!-- <a class="close-reveal-modal">×</a> -->
</div>
I figured it out.
The wmd-prompt-background had a z-index of 1000:
<div class="wmd-prompt-background" style="position: absolute; top: 0px; z-index: 1000; opacity: 0.5; height: 1085px; left: 0px; width: 100%;"></div>
So i just added:
<style type="text/css">
#myModal {
z-index: 1500;
}
</style>
to my page and it worked.
One way to do it is to position the div of your modal directly under the <body>. This way you make sure that the modal is not part of elements with special z-index

Resources