ngx-bootstrap when modal height is dynamic scroll is not coming - javascript

I want to change the height of modal dynamically whenever the content inside the modal is expanding or collapsing. The scenario is I have a collapsible aria inside the modal which expands when view answer button gets clicked. Now while first time loading if content height of modal needs scroll then even after view answer button click everything works fine. But if initial height does not need a scroll that time even after expanding the content scroll is not coming which blocks user to perform further actions.
Screens:
Before expanding screen before clicking view answer button
After expanding screen after clicking view answer button. Here I need scroll otherwise user will get blocked
Code:
<ng-template #template>
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLongTitle">New question</h5>
</div>
<div class="modal-body">
<p class="text-left padding-b-10 border-b-q" [innerHTML]="'Q. ' + questions[nextQuestionIndex].question"></p>
<p class="text-left padding-b-10 border-b-q" (click)="handleOptionClick(i)" *ngFor="let option of questions[nextQuestionIndex].options; let i = index">
{{i + '. '}}<span [innerHTML]="option" [ngClass]="{'text-success': (questions[nextQuestionIndex].answer === i) && optionValidationArr[i],'text-danger': (questions[nextQuestionIndex].answer !== i) && optionValidationArr[i]}"></span><span class="float-right"
[ngClass]="{'text-success': (questions[nextQuestionIndex].answer === i) && optionValidationArr[i]}" *ngIf="(questions[nextQuestionIndex].answer === i) && optionValidationArr[i]">You are right</span><span class="float-right" [ngClass]="{'text-danger': (questions[nextQuestionIndex].answer !== i) && optionValidationArr[i]}"
*ngIf="(questions[nextQuestionIndex].answer !== i) && optionValidationArr[i]">Please try again</span>
</p>
<div class="container">
<p>
<a class="btn btn-outline-danger" data-toggle="collapse" href="#multiCollapseExample1" role="button" aria-expanded="false" aria-controls="multiCollapseExample1">View answer</a>
</p>
<p class="text-danger">This will reduce your score please try your best before viewing the answer</p>
<div class="collapse multi-collapse" id="multiCollapseExample1">
<div class="card card-body">
Correct answer: <span class="text-success">{{questions[nextQuestionIndex].answer}}</span><br> Explaination: <span></span>
</div>
</div>
</div>
<hr />
<div class="progress">
<div class="progress-bar bg-success progress-bar-animated progress-bar-striped" role="progressbar" [style.width.%]="progress.correctPer" [attr.aria-valuenow]="progress.correctPer" aria-valuemin="0" aria-valuemax="100">{{(progress.correctPer ? (progress.correctPer + '%'):'')}}</div>
<div class="progress-bar bg-danger progress-bar-animated progress-bar-striped" role="progressbar" [style.width.%]="progress.wrongPer" [attr.aria-valuenow]="progress.wrongPer" aria-valuemin="0" aria-valuemax="100">{{(progress.wrongPer ? (progress.wrongPer+'%'):'')}}</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-outline-danger" (click)="closeModal()">End practice</button>
<button type="button" class="btn btn-outline-primary" (click)="getNextQuestion(template, resultTemplate)">{{(((questionArrLen-1) !== nextQuestionIndex) ? "Next question" : "View result")}}</button>
</div>
</ng-template>

How about do it like this?
Add a class on modal-body and set height and overflow.
<div class="modal-body question-modal-body">
</div>
.question-modal-body {
max-height: 150px; // set the height which the answer is not shown
overflow: auto;
}

Looks so late to the party, just hope my answer helps someone later. After seeing your screenshot, I suggest having a "Modal scrollable content" approach for your UI. So, only the "content" will expand and push the modal height to the maximum of the screen height ( not over screen height ). So, the modal header and footer will always keep visible, and the content area is scrollable.
Please check the demo on the following Codepen I have made: https://codesandbox.io/s/ngx-boostrap-scrollable-modal-69jox.
It is using:
bootstrap#4.6.1 ( as seen in index.html )
ngx-bootstrap#7.1.2
The trick is to have a special class added to the modal when doing modalService.show(). You can see it at /src/app/app.component.ts
openModal(template: TemplateRef<any>) {
this.modalRef = this.modalService.show(template, {
class: "modal-dialog-centered modal-dialog-scrollable"
});
}
The class name I have mentioned earlier was modal-dialog-scrollable. About modal-dialog-centered is just my personal preference to have the dialog always get centered.
More about "Modal option" used above can be found at the documentation here: https://valor-software.com/ngx-bootstrap/old/5.6.0/#/modals#modal-options
Hope this answer helps someone. Thanks :)

Related

Checkbox input triggering Bootstrap accordion collapse event

Hello guys I'm using Bootstrap 5 accordion, the only problem I have is that the input checkbox is triggering the "collapse" event from the accordion, I tried to move the checkbox outside the range of the button from the accordion but that will look horrible.
I'm using Svelte, rendering each accordion with Each block with Data from the backend!
This is my code right now:
<div class="container">
<div class="row">
<div class="col-md-10 col-10 col-sm-10 responsiveFix">
<div class="accordion" id="accordionObjective">
{#each objectives as objective}
<div class="accordion-item">
<h2
class="accordion-header"
id={"heading" + objective.objectiveId}
>
<button
class="accordion-button objectiveTitle collapsed"
type="button"
data-bs-toggle="collapse"
data-bs-target={"#collapse" +
objective.objectiveId}
aria-expanded="false"
aria-controls={"collapse" +
objective.objectiveId}
>
<div class="form-check">
<input
class="form-check-input"
type="checkbox"
value={objective.objectiveId}
id="myCollapse"
checked={objective.value}
on:click={postObjective(
objective.objectiveId,
objective.value
)}
/>
</div>
<span> {objective.title}</span>
</button>
</h2>
<div
id={"collapse" + objective.objectiveId}
class="accordion-collapse collapse"
aria-labelledby={"heading" +
objective.objectiveId}
data-bs-parent="#accordionObjective"
>
<div class="accordion-body">
<span>{objective.description}</span>
</div>
</div>
</div>
{/each}
</div>
</div>
</div>
</div>
The output of this code its
and this is the picture showing my problem after clicking on any checkbox:
I also tried to bind a bootstrap 5 function to the checkbox input but it didn't work
What can I do? Can you throw me any clue? Thank you!
I am not familiar with Bootstrap 5 as such, but a quick glance at your code shows this: <button on:click={postObjective(objective.objectiveId, objective.value )}>
This function is executed at render time and the return value added as the event listener for your on:click
The correct syntax would be <button on:click={() => postObjective(....)}>
As the code is now it probably does not do what you expect.
Edit:
In your case the input is also inside a button, clicking the input will therefore also click the button. To stop this from happening you have to prevent the event from bubbling up, Svelte has a handy helper for that: <button on:click|stopPropagation={() => postObjective(....)}>

use Angular to hide a div if an image src resolves with 404 Error

I have this piece of code. It get's the logo of a game from steam
<div class="col-md-3">
<img src="http://cdn.edgecast.steamstatic.com/steam/apps/{{game.steamID}}/header.jpg" style="width: 100%; height: auto;"/>
</div>
this is part of a thumbnail div which is tied to a ngFor loop.
now for some context, and my question.
My app uses the steam WebAPI to get a list of all the games a user owns, and stores it in a database.
it then displays the list of these games to the user, with the game logo.
there are some "games" that aren't actually games, dedicated servers mostly.
but these non-games don't have any images attached to them. I want to remove these entries from the webpage whenever they crop up. The best way I can think of is to catch any 404 errors and tell the thumbnail to hide itself.
so my question is, is it possible to use ngIf to hide a div if the image url comes back with a 404 error?
EDIT
I'm adding the entire thumbnail's code for anyone that might want to look a the bigger picture.
<div class="thumbnail" style="color: black" *ngFor="let game of games">
<div class="row">
<div class="col-md-3">
<img src="http://cdn.edgecast.steamstatic.com/steam/apps/{{game.steamID}}/header.jpg" style="width: 100%; height: auto;"/>
</div>
<div class="col-md-9">
<div class="row">
<div class="col-md-12">
<h2>{{game.name}}</h2>
</div>
</div>
<div class="row">
<div class="col-md-12">
<!--<p>{{countRequests(game.id)}} People want to play<span class="pull-right">Sinse: GET_LAST_REQUEST_DATE</span></p>-->
</div>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-md-12">
<div class="centerBlock">
<div class="btn-group btn-group-lg btn-block">
<button *ngIf="page > 1" class="btn btn-primary btn-outline" (click)="previousPage()">Previous</button>
<button *ngFor="let page of pages" class="btn btn-primary btn-outline"(click)="gotoPage(page)">{{page}}</button>
<button *ngIf="page < maxPages" class="btn btn-primary btn-outline" (click)="nextPage()">Next</button>
</div>
</div>
</div>
</div>
Using Angular events you can hide the image itself:
<img #image src="..." (error)="image.hidden = true" [hidden]="image.hidden">
Or any other element:
<div [hidden]="image.hidden"></div>
Or completely remove any div:
<div *ngIf="!image.hidden"></div>
When using *ngFor
Listen to the (error) event of the image element & if the image is broken you can hide the image itself:
<div *ngFor="let some of somethings">
<div *ngIf="some.imageUrl" class="image-class-1 img-class-2">
<img src="{{some.imageUrl}}" (error)="some.imageUrl = null"/>
</div>
</div>
This is what I would do based on what you have said:
1 - I would take the full image url as a property of game.
2 - Also add a property hide to the object.
3 - Consult image using $http service in the controller.
4 - When consulting image the response is 404 then the value of property hide should be true.
5 - As you now have a property hide you can just go ng-hide="game.hide"
Here is an example:
function MyCtrl($scope,$http) {
$scope.games = [{name: 'Game 1', url: 'https://res.cloudinary.com/idemo/image/upload/ar_315:250,c_fill,e_saturation:50,g_faces,r_50,w_450/balloons.jpg'},
{name: 'Game 2', url: 'https://res.cloudinary.com/idemo/image/upload/ar_315:250,c_fill,e_saturation:50,g_faces,r_50,w_450/balloons.jpg'},
{name: 'Game 3', url: ''}]
angular.forEach($scope.games, function(value, key) {
$http.get('value.url').then(function(response){
if(response.status === 404){
value.hide = true
}
});
});
}

jQuery modal pop up disappears when mouse pointer leaves the browser

I'm working on a reactjs project in which i have nav menus, and i'm using jquery modal pop up, one of my menus is "Import" which contains two sub menus "CCAWB & GAWB" i'm using react component to render these two submenus under "Import"
<li className="has-submenu">
<a href="#">
<span>Import</span>
</a>
<ul className="submenu">
<li>
<ul>
<RenderCCAWB_GAWBPopUp submenu ="CCAWB"/>
<RenderCCAWB_GAWBPopUp submenu ="GAWB"/>
</ul>
</li>
</ul>
</li>
RenderCCAWB_GAWBPopUp Component returns the following
render(){
return(<li onClick={this.handleShowModal}>
{this.props.submenu}
{this.state.view.showModal ? <UpdateQualityHeaderDummy
handleHideModal={this.handleHideModal} menuName={this.props.submenu} />:null}
</li>);}
on click of any of the sub menus "CCAWB/GAWB" i want to show the modal pop up
which's returned by another component
UpdateQualityHeaderDummy returns the modal itself
return (
<div className="modal" data-backdrop='static' id="myModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div className="modal-dialog" >
<div className="modal-content">
<div className="modal-header">
<h5 className="modal-title" id="exampleModalLabel">{title}</h5>
<button onClick={this.closePop} type="button" className="close"
data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div className="modal-body">
<div className="row">
<div className=" col-lg-12 col-xl-12
qcUpdateStatus">
</div>
<FileUpload menuTitle={this.props.menuName}/>
</div>
</div>
<div className="modal-footer">
<button type="button" className="btn btn-secondary" data-dismiss="modal" onClick ={this.closePop}>Close</button>
<button type="button" className="btn btn-danger" data-dismiss="modal" onClick ={this.downloadFeed}>Download Feed</button>
<button type="button" className="btn btn-primary" onClick={this.validateForm}> Upload </button>
</div>
</div>
</div>
</div>);
} });
till here everything works fine and the modal shows up as attached bellow
[Screen 1 for the scenario ][1]
*= > the problem is here, whenever the mouse pointer leaves the browser (i.e goes to the url bar) the modal and the sub menus disappear but the modal opacity stays there (attached bellow)
Screen 2 when the pointer is outside the page
*= >but they show up immediately as soon as the pointer is back to the page (any where)
attached bellow screen 3
Screen 3 when the pointer is inside the page
*=> my trials: i have tried the event mouseleave(when mouse leaves the browser) and set the visibility of the sub menus as visible but they keep disappearing i even set the modal show property as true in the same event but also doesn't work.
$(document).mouseleave(function () {
$('.modal').css('visibility','visible');
$('#navigation > div > ul > li:nth-child(5) >
ul').css('visibility','visible');
$('#myModal > div').css('visibility','visible');
$('#myModal > div > div').css('visibility','visible');});
any suggestions please ?

Swipe user media cards left/right to reveal next one

I am trying to implement a widget which ng-repeats user media objects horizontally and I should be able to swipe left/right to reveal the next media card. widget should look something like this
As you can see the image
The next card avatar is half visible, hinting there are more cards to swipe.
this is all i have currently.. i am stuck here
div class="media people-card-media col-xs-12" ng-repeat="item in cats">
<div class="media-left ">
<div class="person-photo presence" >
<img class="media-object list__photo img-circle" ng-src="{{item.photo}}" />
</div>
</div>
<div class="media-body list__body">
<div class="people_name_title">
<h4 class="media-heading title">{{item.name}}</h4>
</div>
</div>
<div class="media-right media-middle contacts-chat-call flex-it-align-top">
<a style="margin-right: 10px;">
call
</a>
</div>
</div>
heres the plunker http://plnkr.co/edit/YESgpGIXQrK9sYl79FVI?p=preview
Here is a plunkr with a working implementation.
http://plnkr.co/edit/wmIyCFM57hniZQ82Z8Ba?p=preview
I added ngTouch and in the HTML a ng-class and the touch event handlers.
<div class="media people-card-media col-xs-12"
ng-class="item.displayClass"
ng-repeat="item in heroes"
ng-click="gonext()"
ng-swipe-left="gonext()"
ng-swipe-right="goprev()">
And in the MainController, it flips through active item by assigning a current class to it, and a next-up and previous class to the neighbors.
$scope.gonext = function () {
for (var i=0, len=$scope.heroes.length; i<len; i++) {
if ($scope.heroes[i].displayClass == 'current') {
$scope.heroes[i].displayClass = 'previous';
if (i<len-1) $scope.heroes[i+1].displayClass = 'current';
if (i<len-2) $scope.heroes[i+2].displayClass = 'next-up';
i=len;
};
};
};
Only needs a better handling of the boundaries.

Hiding individual divs in ng-repeat loop

I have a ng-repeat loop, which displays individual panels (one for each loop iteration). In each panel I have a 'mark as read' button that has a ng-click event. I want to be able to hide the panel that the mark as read button is clicked on, but so far I can only get all the panels to show and hide, not the individual selected panel.
How can I get the ng-click to hide the selected panel?
Thanks
Sorry here is some code of what I am doing now:
The panel section:
<section class="card" ng-repeat="item in notifications" ng-hide="msgRead">
<div class="item item-header notification wrap">
<h2>{{item.title}}</h2>
<div class="notification-content">
{{item.text}}
</div>
<button class="button button-block button-stable" ng-click="markAsRead(item.id)">
Mark As Read
</button>
</div>
</section>
And this is my controller function:
$scope.msgRead = true;
$scope.markAsRead = function (id) {
$scope.msgRead = $scope.msgRead === false ? true : false;
};
Stephen
You can write like:
<section class="card" ng-repeat="item in notifications" ng-hide="item.readonly">
<div class="item item-header notification wrap">
<h2>{{item.title}}</h2>
<div class="notification-content">
{{item.text}}
</div>
<button class="button button-block button-stable" ng-click="item.readonly = true">
Mark As Read
</button>
</div>
</section>
You don't need to write a scope method for this.

Categories