directive works strange in bootstrap grid - javascript

Im AngularJS newbie:).
I have a simple directive driving some popovers for icon. It works ok in one place but in other is working improperly (it blinks and popup is moved down and it covers the icon).
HTML template:
<div class="row">
<div class="col-lg-6">
<h3 class="box-title">EMPLOYEE DETAILS</h3>
<div class="form-group field-userinfo-username">
<label class="control-label text-padding" for="userinfoUsername">Username</label>
<div class="row">
<div class="col-xs-11">
<input type="text" id="uuserinfoUsername" class="form-control" name="userinfoUsername" readonly ng-model="model.full_name" />
</div>
<div class="col-xs-1">
<form-field-information></form-field-information>
<!-- it's not working properly-->
</div>
</div>
<form-field-information></form-field-information>
<!-- it's working properly-->
...
Directive code:
'use strict';
angular.module('app')
.directive('formFieldInformation', function() {
return {
restrict: 'E',
template: '<i class="glyphicon glyphicon-question-sign" style="font-size: 16px" uib-popover="This field describes ..." popover-title="Field information:" popover-trigger="mouseenter"></i>'
//replace: true
};
});
Video added here

Your container (col-xs-1) is too small for the popup to fit inside when displayed. An easy fix is popover-append-to-body="true"
Code:
template: '<i class="glyphicon glyphicon-question-sign" style="font-size: 16px" uib-popover="This field describes ..." popover-append-to-body="true" popover-title="Field information:" popover-trigger="mouseenter"></i>'

Related

Page unresponsive after modal close

A have a webapp developed with Spring boot and thymeleaf a s front end.
We display all the groups available to review. Once user clicks a group we list documents in it tabular form and once user clicks on and document we provide its details. All these I am handling through ajax call and defining on click method. Once user gets to detail section they are provided with more details on that document where they can go and modify or add more through modal. Below is the modal
<!-- Modal start-->
<div id="editModal" tabindex="-1" class="modal fade" role="dialog">
<div class="modal-dialog" role="document">
<!-- Modal content-->
<div class="modal-content">
<div class="modal-header">
<h5 id="pTitle" class="modal-title">Edit</h5>
<button type="button" class="close" data-dismiss="modal">×</button>
</div>
<div class="modal-body">
<div class="row" id="firstNameRow">
<div class="form-group col-sm-12">
<label for="firstName" class="col-sm-4">First Name: </label>
<input class="col-sm-8" type="text" id="firstName" maxlength="32" onkeydown="return validateInputFields(this,event)"/>
<span class="text-danger" style="display:none;float: right;" id="firstNameError">First name is required.</span>
</div>
</div>
<div class="row" id="middleNameRow">
<div class="form-group col-sm-12">
<label for="middleName" class="col-sm-4">Middle Name: </label>
<input class="col-sm-8" type="text" id="middleName" maxlength="32" onkeydown="return validateInputFields(this,event)"/>
<span class="text-danger" style="display:none;float: right;" id="middleNameError"></span>
</div>
</div>
<div class="row has-danger" id="lastNameRow">
<div class="form-group col-sm-12">
<label for="lastName" class="col-sm-4">Last Name: </label>
<input class="col-sm-8 is-invalid" type="text" id="lastName" maxlength="32" onkeydown="return validateInputFields(this,event)" />
<div class="text-danger" style="display:none;float: right;" id="lastNameError" >Last name is required.</div>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-primary" th:onclick="'save();'" id="saveButton" data-backdrop="false" data-keyboard="false">Save</button>
<button type="button" class="btn btn-neutral" data-dismiss="modal">Cancel</button>
</div>
</div>
</div>
</div>
<!--Modal end-->
And here is my save function:
function saveParty(){
var hasError = validateParty();
if(!hasError){
//To close the modal and get back to the previous screen
document.getElementById("saveButton").setAttribute("data-dismiss","modal");
var data = loadPartyDetails();
var objectID = $("#objectID").val();
$.ajax({
type : "POST",
contentType: "application/json",
url: "/saveDetails/" + objectID + "/",
data: JSON.stringify(data),
timeout : 100000,
success : function(result) {
$("#detailsPanel").html(result);
document.getElementById("successMsgParties").style.display="";
$('#successMsgParties').delay(5000).fadeOut('slow');
},
error : function(e) {
console.log("ERROR: ", e);
},
done : function(e) {
console.log("DONE");
}
});
}
}
The call to make modal open:
<td class="text-center"><a th:id="${iter.index + 1}" onclick="populateModal(this);" class="glyphicon glyphicon-pencil" data-toggle="modal" data-target="#editModal"></a></td>
And all this has been working fine. But sometimes all of sudden the whole page hangs up, I cant scroll I cant click on the links and have to refresh the page to continue. There are no errors on the console and have compare the response when the screen freeze and when it doesn't and there is no difference. At this point I am lost on where to look for and what could be the issue. Any directions will be appreciated.
Update: So I found that modal-open class was added but not getting remove when the screen froze, so I added below in my javascript. It does unable to page to scroll but all the links on the page are still disabled.
$("body").removeClass("modal-open");
Alright, I found one more thing, below div element stays there whenever screen freeze. How can I found out which div element is this?
<div class="modal-backdrop fade show"></div>
Any guidelines on how to close the modal appropriately?
Programmatically dismissing a Modal can be done using $('#editModal').modal('hide')
So either the modal is dismissed using the close or cancel button or from the Javascript using the method I shared.
I noticed that the below div element being added which is making screen freeze. I have to hide this through javascript.
<div class="modal-backdrop fade show"></div>

Dynamically duplicating ckeditor, editor doesn't function

I have the following following form where users can add and delete form fields
(i.e. Input type text and textarea).
Further, I've added CKEDITOR as WYSIWYG for all textareas in the form. The below code snippet does generate the new fields successfully and WYSIWYG appears in all the textareas, but I cant input data into the newly generated textareas. I've also checked console and there are no any errors.
What am I missing here? I would be very thankful if anyone could point out the errors I've made.
View on jsFiddle
$(document).ready(function() {
var allEditors = document.querySelectorAll('.editor');
for (var i = 0; i < allEditors.length; ++i) {
CKEDITOR.replace(allEditors[i]);
}
//section add limit
var maxGroup = 10;
//add more section
$(".addMore").click(function() {
if ($('body').find('.fieldGroup').length < maxGroup) {
var fieldHTML = '<div class="row fieldGroup">' + $(".fieldGroupCopy").html() + '</div>';
$('body').find('.fieldGroup:last').after(fieldHTML);
} else {
alert('Maximum ' + maxGroup + ' sections are allowed.');
}
});
//remove fields
$("body").on("click", ".remove", function() {
$(this).parents(".fieldGroup").remove();
});
});
<!-- Bootstrap css library -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<!-- jQuery library -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<!-- Bootstrap js library -->
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<script src="https://cdn.ckeditor.com/4.11.3/standard/ckeditor.js"></script>
<div class="container">
<form method="post">
<div class="row fieldGroup">
<div class="col-md-10 ">
<div class="form-group">
<label for="sectionTitle">Section Title</label>
<input type="text" name="sectionTitle" id="sectionTitle" class="form-control">
</div>
</div>
<div class="col-md-2 ">
<a href="javascript:void(0)" class="btn btn-success addMore">
<span class="glyphicon glyphicon glyphicon-plus" aria-hidden="true"></span> Add
</a>
</div>
<div class="col-md-12 ">
<div class="form-group">
<h4>Section Content</h4>
<textarea name="sectionContent[]" class="editor"></textarea>
</div>
</div>
</div>
<div class="row fieldGroupCopy" style="display: none">
<div class="col-md-10 ">
<div class="form-group floating-label">
<label for="sectionTitle">Section Title</label>
<input type="text" name="sectionTitle" id="sectionTitle" class="form-control">
</div>
</div>
<div class="col-md-2 ">
<span class="glyphicon glyphicon glyphicon-remove" aria-hidden="true"></span> Remove
</div>
<div class="col-sm-12 ">
<div class="form-group">
<h4>Section Content</h4>
<textarea name="sectionContent[]" class="editor"></textarea>
</div>
</div>
</div>
</form>
</div>
I don't think you can create an editor by simply copying the HTML from another instance.
The structure will be duplicated, but the functionality will not.
You'll need to initialize the editor on each <textarea> you add to the page.
In the code below, notice that I've removed the "editor" class from the template HTML. I did that to exclude the template's textarea from the initial editor initialization. New editors will be initiated when they are added to the page.
Also, since you're using jQuery, I suggest using jQuery all the way through for DOM manipulation.
I've added the ckeditor jQuery adapter script.
$(function() {
//section add limit
var maxGroup = 10;
// initialize all current editor(s)
$('.editor').ckeditor();
//add more section
$(".addMore").click(function() {
// define the number of existing sections
var numGroups = $('.fieldGroup').length;
// check whether the count is less than the maximum
if (numGroups < maxGroup) {
// create new section from template
var $fieldHTML = $('<div>', {
'class': 'row fieldGroup',
'html': $("#fieldGroupTemplate").html()
});
// insert new group after last one
$('.fieldGroup:last').after($fieldHTML);
// initialize ckeditor on new textarea
$fieldHTML.find('textarea').ckeditor();
} else {
alert('Maximum ' + maxGroup + ' sections are allowed.');
}
});
//remove fields
$("body").on("click", ".remove", function() {
$(this).parents(".fieldGroup").remove();
});
});
#fieldGroupTemplate {
display: none;
}
<!-- Bootstrap css library -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<!-- jQuery library -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<!-- Bootstrap js library -->
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<!-- ckeditor library and adapter for jQuery -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/ckeditor/4.11.3/ckeditor.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/ckeditor/4.11.3/adapters/jquery.js"></script>
<div class="container">
<form method="post">
<div class="row fieldGroup">
<div class="col-md-10 ">
<div class="form-group">
<label for="sectionTitle">Section Title</label>
<input type="text" name="sectionTitle" id="sectionTitle" class="form-control">
</div>
</div>
<div class="col-md-2 ">
<a href="javascript:void(0)" class="btn btn-success addMore">
<span class="glyphicon glyphicon glyphicon-plus" aria-hidden="true"></span> Add
</a>
</div>
<div class="col-md-12 ">
<div class="form-group">
<h4>Section Content</h4>
<textarea name="sectionContent[]" class="editor"></textarea>
</div>
</div>
</div>
</form>
</div>
<div class="row" id="fieldGroupTemplate">
<div class="col-md-10 ">
<div class="form-group floating-label">
<label for="sectionTitle">Section Title</label>
<input type="text" name="sectionTitle" id="sectionTitle" class="form-control">
</div>
</div>
<div class="col-md-2 ">
<span class="glyphicon glyphicon glyphicon-remove" aria-hidden="true"></span> Remove
</div>
<div class="col-sm-12 ">
<div class="form-group">
<h4>Section Content</h4>
<textarea name="sectionContent[]"></textarea>
</div>
</div>
</div>
I had trouble getting ckeditor to work in a stack snippet.
I get an error about accessing cross-origin iframes:
Uncaught DOMException: Blocked a frame with origin "null" from accessing a cross-origin frame.
So, here's a demonstration on jsFiddle.
For further interest, see this GitHub discussion about automatically initializing editors that are dynamically added to the page. The discussion includes sample code for initializing new editors when they are added, as well as the possibility of using mutation observers to automatically detect and intialize new editors.

ngRepeat doesn't display items

We're working on a e-commerce platform at my work and we use AngularJS. Yesterday we put a great amount (200+, in small quantities it works well) of products in the bag and a bug started, some items aren't listed but it is in the HTML when we inspect elements.
The following codes are what we have:
The directive:
class dSacolaItem{
constructor(){
this.restrict = 'EA';
this.templateUrl = 'views/directives/component-sacola-item.html';
this.scope = {
dirParent: '=?dSacolaItem'
};
}}
The template of the items:
<div class="row block-item" ng-repeat="(key, prod) in dirParent.data track by $index">
<div class="col-xs-12 col-sm-4 col-md-6">
<div class="box-img pull-left">
<img class="img-responsive" ng-src="images/photos/50/{{::prod.imagem}}" d-err-src="images/photos/50/0.jpg" alt="{{::prod.descricao_curta}}">
</div>
<div class="box-infos pull-left">
<h5 class="text-uppercase text-primary" ui-sref="main.produto({ idproduto: {{::prod.id_produto}}, descricao: '{{::prod.descricao_link}}' })">{{::prod.descricao_curta}}</h5>
<small>{{::prod.var1 == undefined ? 'Único' : prod.var1}} | {{::prod.var2 == undefined ? 'Único' : prod.var2}} | {{::prod.var3 == undefined ? 'Único' : prod.var3}}</small>
<button class="btn btn-default btn-xs" type="button" ng-click="dirParent.removeItem(prod.id_variacao)">
<span ng-show="dirParent.removing_prod != prod.id_variacao">remover</span><span ng-show="dirParent.removing_prod == prod.id_variacao"><i class="fa fa-refresh fa-spin"></i></span>
</button>
</div>
</div>
<div class="col-xs-6 col-sm-2 col-md-1 text-center">
<div class="box-gift text-center">
<form name="fGift" ng-submit="false" novalidate>
<label class="gift-prod" ng-if="::(dirParent.configs.produto_preco_presente > 0)">
<input type="checkbox" name="presente" ng-model="prod.presente" ng-change="dirParent.setGift( key, prod.presente )">
<div>
<i class="fa fa-gift fa-3x"></i>
<small>PRESENTE</small>
<small>(R$ {{::dirParent.configs.produto_preco_presente | currency: '': 2}})</small>
</div>
</label>
</form>
</div>
</div>
<div class="col-xs-6 col-sm-2 col-md-1 text-center">
<div class="box-qtde" tooltip-placement="left" uib-tooltip="Em estoque: {{::prod.estoque}}" tooltip-enable="prod.estoque == prod.qtde">
<div class="btn-group btn-group-justified">
<div class="btn-group">
<button class="btn btn-primary" ng-click="dirParent.updateQtde('decrement', key)" ng-class="{'disabled': prod.qtde == 1}"><i class="fa fa-angle-down"></i></button>
</div>
<div class="btn-group">
<button class="btn btn-primary" ng-click="dirParent.updateQtde('increment', key)" ng-class="{'disabled': prod.estoque == prod.qtde}"><i class="fa fa-angle-up"></i></button>
</div>
</div>
<input class="form-control text-center" type="text" ng-value="prod.qtde" disabled="disabled">
<i class="fa fa-refresh fa-spin refresh-qtde" ng-style="dirParent.value_load[key]"></i>
</div>
</div>
<div class="col-xs-6 col-sm-2 box-values text-center">
<span>unitário:</span>
<h5 class="text-primary">R$ {{::prod.preco | currency: '': 2}}</h5>
</div>
<div class="col-xs-6 col-sm-2 box-values text-center">
<span>total:</span>
<h5>R$ {{prod.preco * prod.qtde | currency: '': 2}}</h5>
</div>
I tried to use one-time binding in every place that was possible, but some data needs to be updated...
And finally, how I call the directive:
<div class="shopping-items" d-sacola-item="bag"></div>
I tried to put infinite scroll but it didn't work and also went through a lot of articles trying to fix this but nothing helped.
Some prints of the problem (look to the scroll)
Begin of displayed data (scroll is in 1/3 of the page)
Item not displayed but in the HTML
Anyone with the same problem? I don't know anymore what I should do to fix it.
[add 1]: It seems only browsers that use chromium (Chrome, Opera...) have the issue. Firefox, IE, edge and wow safari 5.1 (2012 version) show everything with some hard work, but at least they display data correctly.

i want to populate my edit form with the data of the selected item

<div class="section" ng-app="ShopMod" ng-controller="myShopsCtrl">
<a class="btn btn-primary btn-fill" href="/addshop">Add a new Shop</a>
<br>
<hr>
<div ng-init="getMyShops()">
<div class="row">
<div ng-repeat="shop in shops">
<div class="col-md-6 col-lg-4 col-sm-12">
<div class="card">
<div class="front">
<div class="cover">
<img src="images/city.jpg" class="img-responsive"/>
</div>
<div class="user">
<img class="img-circle img-responsive" src="images/default-avatar.png"/>
</div>
<div class="content">
<div class="main">
<h3 class="name">{{shop.owner}}</h3>
<h5><i class="fa fa-map-marker fa-fw text-muted"></i> {{shop.address}}, {{shop.state}}</h5>
<h5><i class="fa fa-building-o fa-fw text-muted"></i> {{shop.contact}}</h5>
<h5><i class="fa fa-envelope-o fa-fw text-muted"></i> {{shop.email}}</h5>
</div>
<div class="footer">
<a href="/editshop/:{{shop.id}}">
Edit |
</a>
<a ng-click="manageShop(shop.id)">
Manage |
</a>
<a ng-click="editShop(shop.id)">
Delete
</a>
</div>
</div>
</div> <!-- end front panel -->
</div> <!-- end card -->
</div> <!-- end card-container -->
</div>
</div>
</div>
</div>
</div>
I'm new to sails and angular and i'm having an issue populating my edit form. I have a list of items, code is above. the user clicks the edit link and it takes them to a page,code is below, that will be populated with the data of that selected item.
<div class="section" ng-app="ShopMod" ng-controller="editShopCtrl">
<div class="header text-center">
<h2 style="text-decoration: underline">Edit Shop</h2>
</div>
<div class="content">
<form ng-submit="updateShop()">
<div class="form-group">
<label for="name">Shop Name</label>
<input type="text" class="form-control" ng-model="name" value="{{shop.name}}">
</div>
<div class="form-group">
<label for="address">Shop Address</label>
<input type="text" class="form-control" ng-model="address" value="{{shop.address}}">
</div>
<div class="form-group col-md-6">
<label for="contact">Phone Number</label>
<input type="tel" class="form-control" ng-model="contact" value="{{shop.contact}}">
</div>
<div class="form-group col-md-6">
<label for="email">Shop Email</label>
<input type="email" class="form-control" ng-model="email" value="{{shop.email}}">
</div>
<div class="form-group col-md-6">
<label for="email">State</label>
<select class="form-control" ng-model="state" value="{{shop.state}}">
<option>Lagos</option>
<option>Abuja</option>
</select>
</div>
<div class="col-md-8">
<button type="submit" class="btn btn-fill btn-info">Update Shop</button>
</div>
</form>
</div>
</div>
I know how to get the id of the selected item, and pass it to my back-end controller, my issue is sending that data back from my back-end controller to my form which is basically another view.Below is my function for getting the id from the url,finding the corresponding data and returning it.
editShop:function (req, res)
{
var id = req.param('id');
Shops.findOne({id:id},
function (err, shop)
{
if(err)
{
return res.negotiate(err);
}
return res.send(shop.data)
})
}
Below is the code for how i'm handling the routing
'GET /editshop/:id':{
view:'Shops/editShop',
locals: {
layout: '/Dashboard/layout-admin',
}
}
i would like to know how to go about dealing with this situation.
According to your scenario on click you want to load another page with edit layout. Ejs lets you bind the data you want at backend And so that you can send the data after bind.
But i do it different way.
SAVE All Detail to localStorage of the browser
I am completing only some of your code you can easily see where and what you should do.....
angular.module('ShopMod', [])
.controller('myShopsCtrl', ['$scope', '$http', function ($scope, $http) {
$scope.getMyShops = function (id) {
$http.get('/shops?id=' + id)
.then(function (res) {
if (Array === res.data.constructor)//if res.data is array
$scope.shop = res.data[0];
else //res.data is object.
$scope.shop = res.data;
localStorage.setItem('myShop', JSON.stringify($scope.shop));
}, function (err) {
$scope.shop = {};
console.log(err);
});
}
}]);
In the above...
GET request is made at lcalhost:1337/shops?id=43 (Let shop id is
43).which is a blueprint route(sails make it for you by default
for rapid development).
$scope.shop is initialized with res.data and the same is saved in browsers localStorage by key myShop.Which you can access anytime.(you can see local storage in developer console Resources).
So all you have to do is to load the edit page.
<div class="footer">
<a href="/editshop/">
Edit |
</a>
<a ng-click="manageShop(shop.id)">
Manage |
</a>
<a ng-click="editShop(shop.id)">
Delete
</a>
</div>
Back-end Route for loading edit template.
'GET /editshop/':{
view:'Shops/editShop',
locals: {
layout: '/Dashboard/layout-admin',
}
}
In your edit template.
make ng-init="initializeForm()" at top.
and write controller function.
angular.module('ShopMod', [])
.controller('editShopCtrl', ['$scope', '$http', function ($scope, $http) {
$scope.getMyShops = function (id) {
$scope.shop=JSON.parse(localStorage.myShop);
}
}]);
Putting data from localStorage to current $scope.shop...
This is how i do!I hope it will work for you!

Semantic UI Modal only shows up once in Meteor

I have got a meteor app which uses the Semantic UI. I am using the semantic:ui-css package for this.
I have got a template called project where I want to show a modal.
There for I created a second template which is the modal like this:
<template name="xform">
<div id="modal" class="ui modal">
<i class="close icon"></i>
<div class="header">New Project</div>
<div class="content">
<div class="ui form" id="newProject">
<div class="one fields">
<div class="field">
<legend>Project Details</legend>
<label>Name</label>
<input id="name" name="name" type="text" placeholder="Project name">
</div>
<input type="submit" class="button small createProject" style="color:white;position:relative;float:right;padding: 0.875rem 1.75rem 0.9375rem 1.75rem;font-size: 0.8125rem;" value="Create">
</div>
</div>
</div>
<div class="actions">
<div class="ui button">
Cancel
</div>
<div class="ui button">
Okay
</div>
</div>
</div>
</template>
Then I haved added a event to a button like this to show the modal:
Template.projects.events({
'click .newProject': function(event, template){
template.$('.ui.modal').modal({
onDeny : function(){
return false;
}}).modal('show');
}
});
If I click the button for the first time the modal opens like wanted.
I can see that the modal is now not anymore inside the html of my template but at the end of my body.
I can close the modal using the close button but when I now try to open it again it does not open any more.
The modal div is still on the bottom of my body.
I have tried several ways to workaround this problem but none have worked.
Here my complete code: http://i.imgur.com/r9JNrlr
To follow up from my comment, this is the code that is working for me. It definitely seems like you have an issue with jQuery finding multiple elements. I created a new meteor project:
$ meteor create semantic
$ cd semantic
$ meteor add semantic:ui-css
$ meteor add iron:router
semantic.html
<template name="MainLayout">
<h1>Title</h1>
{{> yield}}
</template>
<template name="projects">
{{> xform}}
<button class="newProject">New Project</button>
</template>
<template name="xform">
<div id="modal" class="ui modal">
<i class="close icon"></i>
<div class="header">New Project</div>
<div class="content">
<div class="ui form" id="newProject">
<div class="one fields">
<div class="field">
<legend>Project Details</legend>
<label>Name</label>
<input id="name" name="name" type="text" placeholder="Project name">
</div>
<input type="submit" class="button small createProject" style="color:white;position:relative;float:right;padding: 0.875rem 1.75rem 0.9375rem 1.75rem;font-size: 0.8125rem;" value="Create">
</div>
</div>
</div>
<div class="actions">
<div class="ui button">
Cancel
</div>
<div class="ui button">
Okay
</div>
</div>
</div>
</template>
semantic.js
if (Meteor.isClient) {
Template.projects.events({
'click .newProject': function(event, template){
$('.ui.modal').modal({
onDeny : function(){
return false;
}}).modal('show');
}
});
Meteor.startup(function() {
Router.configure({
layoutTemplate: 'MainLayout'
})
Router.route('/',{
name: 'projects'
})
});
}
After running meteor and loading http://localhost:3000 I can open and close the modal multiple times.
Try to set the modal non-detachable in onRendered callback function of template.
Template.projects.onRendered(() => {
$('.ui.modal').modal({ detachable: false });
});
Hope it helps.

Categories