ng-repeat to open content - html

I am trying to make a list of buttons appear, and once selected for the appropriate div underneath the button to be shown, I have used similar code before:
<li><button class="w3-button w3-grey w3-hover-dark-grey w3-round-xxlarge" ng-click="section = !section">Structure and function of the processor</button></li>
Which works fine so I am guessing it has something to do with $index
Do you have any idea how I could achieve this?
<div class="w3-panel" ng-show="section">
henlo content
</div>
<div ng-app="tApp" ng-controller="tController">
<ul class="w3-ul">
<div ng-repeat="x in items">
<li>
<button class="w3-button w3-grey w3-hover-dark-grey w3-round-xxlarge" ng-click="section{{$index}} = !section{{$index}}">{{x.name}}</button>
</li>
<div class="w3-panel" ng-show="section{{$index}}">
{{x.content}}
</div>
</div>
</ul>
</div>
<script>
var app=angular.module("tApp", []);
app.controller("tController", function($scope)
{
$scope.items=[{name:"first",content:"henlo first"},{name:"second", content:"henlo second"}];
});
</script>

you can initialise a property with ng-init and use that property to show/hide content
<div ng-repeat="x in items" ng-init="x.displayContent = false">
<li>
<button class="w3-button w3-grey w3-hover-dark-grey w3-round-xxlarge" ng-click="x.displayContent = !x.displayContent">{{x.name}}</button>
</li>
<div class="w3-panel" ng-show="x.displayContent">
{{x.content}}
</div>
</div>

Related

Bind child element position to parent element

I have a navigation that is horizontal. Under every choice I have a div that opens up on click. But the problem is that it binds it's position to the parent navigation button. I want every div that opens on the exact same spot. I want every child div that opens to open from the first element in the navigation bar.
So in this case i want the white open div to bind to "Nyheter" instead. I really can't solve it, I tried set a div element before the navigation that all div that opens binds to in css but it not seems to work.
<div class="Container">
<nav class="NavHorizontal Grid Grid--alignMiddle">
#Navigation.RenderNavigation("master/navigationDesignHeader.cshtml", navigationSettings)
</nav>
</div>
//NavigationDesignheader.cshtml under this line
var elementId = 1;
foreach (var node in nodes)
{
var idElement = "megaMenu" + elementId;
<div class="NavHorizontal-item Grid-cell u-sizeFit" id="#idElement">
<a class="Button Button--tab navigationHeaderLink u-pointer" onclick="toggleMenu('#elementId')">
#node.Name
</a>
#RenderMegaMenu(node.Nodes, node.Link, node.Name)
</div>
elementId++;
}
Megamenu:
<div>
<div id="megaMenuDropdown" class="Container megaMenuDropdown-content displayNone">
<div class="Grid Grid--withGutter">
<div class="Grid-cell u-sizefull u-mt-10">
#nodeName
<div class="megaMenuToggle-closeBars u-pointer" style="float:right">
<span class="megaMenuToggle-closeBar"></span>
<span class="megaMenuToggle-closeBar"></span>
</div>
</div>
</div>
<hr class="colorBlue" />
<div class="Grid Grid--withGutter">
<div class="Grid-cell u-size12of12 u-md-size6of12 u-lg-size6of12">
<ul>
#foreach (var node in firstColumn)
{
<li class="u-mb-10 linkHover">
<a class="userLink colorBlue" href="#node.Link">#node.Name</a>
</li>
}
</ul>
</div>
#if (moreThanTen)
{
<div class="Grid-cell u-size12of12 u-md-size6of12 u-lg-size6of12">
<ul>
#foreach (var node in secondColumn)
{
<li class="u-mb-10 linkHover">
<a class="userLink colorBlue" href="#node.Link">#node.Name</a>
</li>
}
</ul>
</div>
}
</div>
</div>
</div>
Any suggestions?

Dynamically added modals aren't triggering

I am loading cards and there modals dynamically and the problem I am facing is that the dynamically added cards aren't triggering the dynamically added modals.
The cards are this
data.forEach(eve => {
console.log(eve.data());
event = eve.data();
pastEventCards+=`
<li class="cards_item">
<div class="card">
<div class="card_image">
<img src="images/posters/cpp_2021.jpeg" />
</div>
<div class="card_content card-body d-flex flex-column">
<h2 class="card_title">${event.title}</h2>
<p class="card_text">
</p>
**<button data-modal-trigger="past-event-modal-${event.eventNo}" class="mt-auto demo__btn demo__btn--secondary">
Read More
</button>**
</div>
</div>
</li>
`
pastEventModals+=`
<div class="modal" data-modal-name="past-event-modal-${event.eventNo}">
<div class="modal__dialog">
<button class="modal__close" data-modal-dismiss>×</button>
<header class="modal__header">
<h2 class="modal__title">${event.title}</h2>
</header>
<div class="modal__content">
<h4 class="modal_description">Description</h4>
</p>
<p>${event.description}</p>
<p class="modal_description">
${event.date}
</p>
<p class="modal_description">Attendees : ${event.attendee}
</p>
<p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-modal-dismiss>Close</button>
</div>
</div>
</div>
`
});
cardsList.innerHTML = pastEventCards ;
modalList.innerHTML = pastEventModals ;
I have tried referring to other stack overflow questions related to this and couldnt find a understandable solution to why this is happening , can anyone tell why the buttons cant trigger the modals ?
**EDIT :: **
The button that triggers the modal is inside this ** ** in the pastEventCards variable and the modal is in pastEventModals and when i use "data-modal-trigger = "something" " it will trigger the modal with modal name "something" right ? So y isnt it happening. If I dont add this modals and trigger cards dynamically and add it in the html template then it works fine but after adding dynamically it doesnt work

How I can take data from a json inside a ng-init in the view

I have a json inside a ng-init where I have some data and I want to grab these data and paint into a template and I compiled with my directive and I don't have idea what I'm doing wrong. I can not paint json data into the template
example:
<li ng-init="product= {"brand":"Nike", "price":"30€", "mainImage":"images/images.jpg"}>
<div class="content-product>
<div class="product">
<p>Nike </p>
<img src="image.jpg" alt="">
<p>30€ </p>
</div>
</div>
</li>
This li is inside a loop in ruby.
Template where I want to paint the data and compile this template when I click on a button that is inside the li:
<script type="text/ng-template" id="quickpreview.html">
<div class="content-preview">
<div class="content-preview-inner">
<span class="full-preview"></span>
<span class="close-preview"></span>
<div class="block block-left left">
<div class="content-tabs">
<dl class="tabs vertical" data-tab>
<dd class="active">Tab 1
</dd>
<dd>Tab 2
</dd>
<dd>Tab 3
</dd>
<dd>Tab 4
</dd>
<dd>Tab 5
</dd>
</dl>
<div class="tabs-content vertical">
<div class="content active" id="panel1">
<div class="content-img">
<div class="main-img">
<img ng-src="{{product.mainImage}}" alt="">
</div>
<div class="thumbnails">
<a class="th" role="button" aria-label="Thumbnail" href="">
<img aria-hidden=true src="" />
</a>
</div>
</div>
</div>
<div class="content" id="panel2">
<p>This is the second panel of the basic tab example. This is the second panel of the basic tab example.</p>
</div>
<div class="content" id="panel3">
<p>This is the third panel of the basic tab example. This is the third panel of the basic tab example.</p>
</div>
<div class="content" id="panel4">
<p>This is the fourth panel of the basic tab example. This is the fourth panel of the basic tab example.</p>
</div>
<div class="content" id="panel5">
<p>This is the fifth panel of the basic tab example. This is the fourth panel of the basic tab example.</p>
</div>
</div>
</div>
</div>
<div class="block block-right right">
<div class="content-details">
<div class="details">
<h3 class="title-product">{{product.brand}}</h3>
<h2 class="short-desc">{{product.shortname}}</h2>
<div class="block-price">
</div>
</div>
</div>
</div>
</div>
</div>
my directive and controller:
(function() {
'use strict';
var app = angular.module('quickPreview');
app.controller('globalCtrl', function ($scope) {
// var e = angular.element($("[ng-init]"));
// console.log(e);
// $scope.product = e.attr('ng-init');
// console.log($scope.product);
$scope.product = [];
var logSomeStuff = function(){
console.log($scope.product);
}
$scope.$evalAsync(logSomeStuff);
});
}(window, window.angular));
(function (){
"use strict";
var app = angular.module('quickPreview');
app.directive('previewProduct', function ($compile,$templateCache) {
return {
restrict: 'A',
replace: false,
transclude: false,
scope: {
attrData: '=dataOverview'
},
link: function(scope, element, attrs) {
element.bind('click', '.sd-click-preview', function (){
var preview = angular.element($templateCache.get('quickpreview.html'));
var cpreview = $compile(preview);
element.append(preview);
cpreview(scope);
console.log(cpreview(scope))
if (scope.attrData) {
console.log(this, '=> this');
}
});
}
};
});
}(window, window.angular));
You don't need quotes in ng-init statement. You are ending the statement prematurely.
<li ng-init="product= {brand:'Nike', price:'30€', mainImage:'images/images.jpg'}">
<div class="content-product">
<div class=" product ">
<p>{{product.brand}}</p>
<img ng-src="{{product.mainImage}} " alt=" ">
<p>{{product.price}}</p>
</div>
</div>
</li>
Here's a working example:http://plnkr.co/edit/XRyYefxncZuqE5GeA3XG?p=preview

AdminLTE collapsed boxes by default

AdminLTE is based on Bootstrap: https://github.com/almasaeed2010/AdminLTE
Live Preview: http://almsaeedstudio.com/preview/
But I'm unsure as to how to make the collapsable boxes collapsed by default.
I'm assuming since it is built on Bootstrap, this should be rather straightforward. I've tried fellow implementations such as setting the id to "collapsedOne" and attempting to treat the divs as accordions, but to no avail.
On the AdminLTE/app.js ~line 45 there is code that implements slide up/slide down to collapse boxes. Ideally, what we'd want is to have the boxes be in the "slide up" state by default with the class "collapsed-box" so that when the icon is clicked, it executes "slide down".
/*
* Add collapse and remove events to boxes
*/
$("[data-widget='collapse']").click(function() {
//Find the box parent
var box = $(this).parents(".box").first();
//Find the body and the footer
var bf = box.find(".box-body, .box-footer");
if (!box.hasClass("collapsed-box")) {
box.addClass("collapsed-box");
bf.slideUp();
} else {
box.removeClass("collapsed-box");
bf.slideDown();
}
});
Any suggestions?
Thanks in advance.
When the page loads in its initial state, why not just add the collapsed-box class to box element?
The below will render in the collapsed state and function without modifying AdminLTE:
<!-- Default box -->
<div class="box box-solid collapsed-box">
<div class="box-header">
<h3 class="box-title">Default Solid Box</h3>
<div class="box-tools pull-right">
<button class="btn btn-default btn-sm" data-widget="collapse"><i class="fa fa-plus"></i></button>
<button class="btn btn-default btn-sm" data-widget="remove"><i class="fa fa-times"></i></button>
</div>
</div>
<div style="display: none;" class="box-body">
Box class: <code>.box.box-solid</code>
<p>bla bla</p>
</div><!-- /.box-body -->
</div><!-- /.box -->
$("[data-widget='collapse']").click() Add that to a JavaScript file that runs at the bottom
Here are the steps:
Change the minus icon to plus .
Add explicit style "display:none" to box-body
Add the class "collapsed-box" to the box
For those who are using AdminLTE 2.1.1
just simply add sidebar-collapse class on the <BODY>
Before:
<body class="skin-blue sidebar-mini">
After:
<body class="skin-blue sidebar-mini sidebar-collapse">
An open box:
<div class="box">
A collapsed box:
<div class="box collapsed-box">
And then ofcourse change the icon on the button
In Admin LTE 3 collapse by default by using the class collapsed-card on the main card.
Like this
<div class="col-md-3">
 <div class="card collapsed-card">
   <div class="card-header" >
     <h3 class="card-title">Expandable</h3>
     <div class="card-tools">
       <button type="button" class="btn btn-tool" data-card-widget="collapse"><i class="fas fa-plus"></i>
       </button>
     </div>
   </div>
   <div class="card-body" >
     The body of the card
   </div>
 </div>
</div>
You should change the icon to a fas fa-plus then the initial box starts with a plus
$("[data-widget='collapse']").click(function() {
//Find the box parent........
var box = $(this).parents(".box").first();
//Find the body and the footer
var bf = box.find(".box-body, .box-footer");
if (!$(this).children().hasClass("fa-plus")) {.
$(this).children(".fa-minus").removeClass("fa-minus").addClass("fa-plus");
bf.slideUp();
} else {
//Convert plus into minus
$(this).children(".fa-plus").removeClass("fa-plus").addClass("fa-minus");
bf.slideDown();
}
});
and use in section div
for one specify div
$(function() { $('your-button-id').click(); })
for all
$(function() { $("[data-widget='collapse']").click(); })
Simply add "collapsed-box" to the box and change this:
<button class="btn btn-box-tool" data-widget="collapse"><i class="fa fa-minus"></i></button>
to
<button class="btn btn-box-tool" data-widget="collapse"><i class="fa fa-plus"></i></button>
This should work for me
The correct tested Steps which worked for me are :
Add explicit style "display:none" to box-body
You are done :)
<div class="box ">
<div class="box-header with-border bg-yellow">
<h3 class="box-title">Box Title Here</h3>
<div class="box-tools pull-right">
<button class="btn btn-box-tool" data-widget="collapse"><i class="fa fa-minus"></i></button>
<button class="btn btn-box-tool" data-widget="remove"><i class="fa fa-times"></i></button>
</div>
</div><!-- /.box-header -->
<div class="box-body" style="display: none;">
<div class="table-responsive">
<!--Your content here -->
</div><!-- /.table-responsive -->
</div><!-- /.box-body -->
</div>
<div class="box box-default collapsed-box">
<div class="box-header with-border">
<h3 class="box-title">Expandable</h3>
<div class="box-tools pull-right">
<button class="btn btn-box-tool" data-widget="collapse"><i class="fa fa-plus"></i></button>
</div><!-- /.box-tools -->
</div><!-- /.box-header -->
<div class="box-body">
The body of the box
</div><!-- /.box-body -->
</div><!-- /.box -->
This soluction worked for me:
I added "collapse-left" class for the menu and added the "strech" class for the main content.
I use the version 1 for the AdminLTE. It is divided in aside class="left-side" for the left menu and aside class="right-side" for the main content.
So, this is the final code:
<aside class="left-side collapse-left">
<!-- put the left menu here -->
</aside>
<aside class="right-side strech">
<!-- put the main content here -->
</aside>
I added this to the boxWidget object:
setInitialCollapseStatus: function (container) {
var _this = this;
var collapsedBoxes = container.find('.box.collapsed-box .btn-box-tool > i');
collapsedBoxes.each(function (index) {
var box = $(this);
//Convert minus into plus
box
.removeClass(_this.icons.collapse)
.addClass(_this.icons.open);
});
}
and called it during initializiation:
activate: function (_box) {
var _this = this;
if (!_box) {
_box = document; // activate all boxes per default
}
//Listen for collapse event triggers
$(_box).on('click', _this.selectors.collapse, function (e) {
e.preventDefault();
_this.collapse($(this));
});
//Listen for remove event triggers
$(_box).on('click', _this.selectors.remove, function (e) {
e.preventDefault();
_this.remove($(this));
});
// Set initial collapseStatus
_this.setInitialCollapseStatus($(_box));
},
Add css classes into body tag in the index.html file:
sidebar-closed sidebar-collapse
<body class="hold-transition sidebar-mini sidebar-closed sidebar-collapse layout-fixed layout-navbar-fixed layout-footer-fixed">
With Adminlte 3:
Card Parent add ID: <div class="card card-default" id="a">
Change <i class="fas fa-minus"></i> TO => <i class="fas fa-plus"></i>
Add Display:none <div class="card-body" style="display:none">
Add jquery $('#a').CardWidget('toggle');

Multiple transclusions of separate html

I'd like to transclude multiple pieces into one directive. Here is my idea of how I'd set it up.
<div id="content" class="mainDirective">
<div class="sub">
<ul>
<li>Everyone</li>
<li>Development (3)</li>
<li>Marketing</li>
</ul>
</div>
<div class="subButtons">
<span class="csStIcon add" data-ng-click="addTeam()"></span>
<span class="csStIcon edit" data-ng-click="editTeam()"></span>
<span class="csStIcon delete" data-ng-click="deleteTeam()"></span>
</div>
<div class="main">
<table>
<thead>
<tr><td>Name</td><td>Last name</td><td>Department</td></tr>
</thead>
<tbody>
<tr><td>Lorem</td><td>Ipsum</td><td>Development</td></tr>
<tr><td>Lorem</td><td>Ipsum</td><td>Development</td></tr>
<tr><td>Lorem</td><td>Ipsum</td><td>Development</td></tr>
</tbody>
</table>
</div>
</div>
My directive template:
<div>
<div class="left">
<div data-ng-multi-transclude="sub"></div>
<div class="bottomOptions">
<span class="csStIcon collapse"></span>
<div data-ng-multi-transclude="subButtons"></div>
</div>
</div>
<div class="right">
<div data-ng-multi-transclude="main"></div>
</div>
</div>
And the final output:
<div>
<div class="left">
<div class="sub">
<ul>
<li>Everyone</li>
<li data-ng-click="loadDepartment()">Development (3)</li>
<li data-ng-click="loadDepartment()">Marketing</li>
</ul>
</div>
<div class="bottomOptions">
<span class="csStIcon collapse"></span>
<div class="subButtons">
<div class="subButtons">
<span class="csStIcon add" data-ng-click="addTeam()"></span>
<span class="csStIcon edit" data-ng-click="editTeam()"></span>
<span class="csStIcon delete" data-ng-click="deleteTeam()"></span>
</div>
</div>
</div>
</div>
<div class="right">
<div class="main">
<table>
<thead>
<tr><td>Name</td><td>Last name</td><td>Department</td></tr>
</thead>
<tbody>
<tr><td>Lorem</td><td>Ipsum</td><td>Development</td></tr>
<tr><td>Lorem</td><td>Ipsum</td><td>Development</td></tr>
<tr><td>Lorem</td><td>Ipsum</td><td>Development</td></tr>
</tbody>
</table>
</div>
</div>
</div>
Is this possible within angular?
I ended up needing this functionality as well, so I wrote ng-multi-transclude -- funnily enough, I hadn't seen this question at the time, just lucked into the same name.
Usage is almost exactly as your question sketches; the only difference is that you use the name attribute to pick the "hole" to fill instead of the class attribute.
This has been added in angular 1.5
http://angularjs.blogspot.ca/2016/02/angular-150-ennoblement-facilitation.html
I came up with this directive using transclude function:
app.directive('mainDirective', function($compile) {
var template = ['<div>',
' <div class="left">',
' <div data-ng-multi-transclude="sub"></div>',
' <div class="bottomOptions">',
' <span class="csStIcon collapse"></span>',
' <div data-ng-multi-transclude="subButtons"></div>',
' </div>',
' </div>',
' <div class="right">',
' <div data-ng-multi-transclude="main"></div>',
' </div>',
'</div>'].join('\n');
return {
restrict: 'C',
transclude: true,
template: template,
link: function(scope, element, attr, model, transclude) {
var places = element.find('[data-ng-multi-transclude]');
console.log(element);
places.each(function() {
var self = $(this);
var class_ = self.data('ng-multi-transclude');
transclude(scope.$new(), function(clone, scope) {
var item = clone.closest('.' + class_);
$compile(item)(scope).appendTo(self);
});
});
}
};
});
I've used compile so you can use angular inside your transcluded code.
If you use this:
self.replaceWith($compile(item)(scope));
you'll don't get those original wrappers divs with data-ng-multi-transclude attributes.
Also you need to have jQuery included (always before Angular, because otherwise you get jQLite instead).
I have used multiple 'transclusions' in the component I am writing. In practice, it's just nested directives but they get the job done: https://github.com/AlexCppns/ac-fancy-input
More specifically, have a look at the following file:
https://github.com/AlexCppns/ac-fancy-input/blob/master/src/ac-fancy-input/directives/fancy-input.js