I've been stuck on something for some time now and need some help. I'm trying to build a tab control that allows me to dynamically add tabs with HTML content. The tab control that I found uses an id element to reference the url for the tab. What' I've found is that I can hardcode the id with my tab name and it will work, but if I use an expression {{eisEvent.url}} the $compile will not evaluate this to the real name. I would have put this in a fiddle, but JSFiddle is having some major problems today, so I'll paste the code instead. It's just three files.
style.css
ul {
list-style: none;
padding: 0;
margin: 0;
}
li {
float: left;
border: 1px solid #000;
border-bottom-width: 0;
margin: 3px 3px 0px 3px;
padding: 5px 5px 0px 5px;
background-color: #CCC;
color: #696969;
}
#mainView {
border: 1px solid black;
clear: both;
padding: 0 1em;
}
.active {
background-color: #FFF;
color: #000;
}
tabs.js
var myApp = angular.module('TabsApp', []);
myApp.service('EISEventService', function($rootScope) {
var eisSubscriptions = [];
this.addSubscription = function( eisEvent ){
console.log( eisEvent.name + "\n" + eisEvent.message );
$rootScope.$broadcast( "EVENT_ADDED", eisEvent );
eisSubscriptions.push( eisEvent );
};
this.removeSubscription = function( eisEvent ){
//TODO Remove the element from the array.
$rootScope.$broadcast( "EVENT_REMOVED", eisEvent );
};
});
myApp.controller('TabsCtrl', function ($scope, EISEventService) {
console.log("Initializing Tab Controller");
$scope.eisEvent = {};
$scope.tabs = [{
title: 'One',
url: 'one.tpl.html'
}, {
title: 'Two',
url: 'two.tpl.html'
}];
$scope.currentTab = 'one.tpl.html';
$scope.onClickTab = function (tab) {
$scope.currentTab = tab.url;
};
$scope.isActiveTab = function(tabUrl) {
return tabUrl == $scope.currentTab;
};
$scope.$on('EVENT_ADDED', function( event, args ){
console.log( "EventName : " + event.name );
var eisEvent = args;
console.log("EIS Event = " + eisEvent.name );
console.log("Message = " + eisEvent.message );
console.log("URL = " + eisEvent.url );
$scope.eisEvent = eisEvent;
$scope.tabs.push( {title : eisEvent.name, url:eisEvent.url });
// By doing this, it seems to work, but I need the second option to work because I will eventually retrieve this HTML from
// the server that will need to be parsed.
// Option 1
$scope.tabs_html.push( {html: '<script type="text/ng-template" id="'+eisEvent.url+'">Hello Event: '+eisEvent.name+'</script>' });
// Option 2
//This doesn't appear to work because of the binding.
//$scope.tabs_html.push( {html: '<script type="text/ng-template" id="{{eisEvent.url}}">Hello Event: {{eisEvent.url}}</script>' });
// Option 3
//If I hard code the ID it will work. For example if I enter test in the text box on the demo, the code below will work.
//$scope.tabs_html.push( {html: '<script type="text/ng-template" id="test_url">Hello Event: {{eisEvent.url}}</script>' });
});
$scope.tabs_html = [];
});
myApp.controller('AddCtrl', function($scope, EISEventService) {
$scope.onAddClick = function(){
console.log("add clicked");
var eisEvent = { name : $scope.txtName, url: $scope.txtName+"_url", message: "This is a log message"};
EISEventService.addSubscription(eisEvent);
}
});
myApp.directive("bindCompiledHtml", function($compile, $timeout) {
return {
template: '<div></div>',
scope: {
rawHtml: '=bindCompiledHtml'
},
link: function(scope, elem, attrs) {
scope.$watch('rawHtml', function(value) {
if (!value) return;
// we want to use the scope OUTSIDE of this directive
// (which itself is an isolate scope).
var newElem = $compile(value)(scope.$parent);
elem.contents().remove();
elem.append(newElem);
});
}
};
});
And Lastly tabs.html
<!DOCTYPE html>
<html ng-app="TabsApp">
<head>
<title></title>
<link rel="stylesheet" type="text/css" href="style.css">
<!--<script src="../lib/angular.min.js"></script>-->
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.21/angular.min.js"></script>
<script src="tabs.js"></script>
</head>
<body >
<div>
<div id="add" ng-controller="AddCtrl">
<input type="text" ng-model="txtName">
<button ng-click="onAddClick()">Add</button>
</div>
<div id="tabs" ng-controller="TabsCtrl">
<ul>
<li ng-repeat="tab in tabs"
ng-class="{active:isActiveTab(tab.url)}"
ng-click="onClickTab(tab)">{{tab.title}}</li>
</ul>
<div id="mainView">
<div ng-include="currentTab"></div>
</div>
<script type="text/ng-template" id="one.tpl.html">
<div>
<h1>View One</h1>
<p>Praesent id metus massa, ut blandit odio. Proin quis tortor orci. Etiam at risus et justo dignissim congue. Donec congue lacinia dui, a porttitor lectus condimentum laoreet. Nunc.</p>
</div>
</script>
<script type="text/ng-template" id="two.tpl.html">
<div>
<h1>View Two</h1>
<p>Curabitur vulputate, ligula lacinia scelerisque tempor, lacus lacus ornare ante, ac egestas est urna sit amet arcu. Class aptent taciti sociosqu.</p>
</div>
</script>
<script type="text/ng-template" id="three.tpl.html">
<div>
<h1>View Three</h1>
<p>In pellentesque faucibus vestibulum. Nulla at nulla justo, eget luctus tortor. Nulla facilisi. Duis aliquet egestas purus in blandit. Curabitur vulputate, ligula lacinia scelerisque tempor, lacus lacus ornare ante, ac egestas est urna sit amet arcu. Class aptent taciti sociosqu.</p>
</div>
</script>
<div>
<div ng-repeat="tab in tabs_html" bind-compiled-html="tab.html"></div>
</div>
</div>
</div>
</body>
</html>
You can just run the app, type in some text and click the add button. This will add a tab with the URL that's the same. See the JavaScript comments in the JS file for Option 1, Option 2, and Option 3. Currently Option 1 is uncommented to show that it works. If you comment this out and uncomment Option 2, this is the option that I need to work but cannot get it to work.
I've made a Plunk for you
What if you $compile the html first, like this
var htmlString = '<script type="text/ng-template" id="{{eisEvent.url}}">Hello Event: {{eisEvent.url}}</script>';
var htmlElement = $compile(htmlString)($scope);
$scope.tabs_html.push( {html: htmlElement });
You must of course inject the compile service
myApp.controller('TabsCtrl', function ($scope, EISEventService, $compile) {
Related
What's the best way to create menu like in attached photos ?
I tried to make it with:
const [firstParentActive, setFirstParentActive] = useState(false) // idea is to make useStates for all category parents and category children
const activeHandler = () => {...} // all handlers for setting 'true' in such category parents
<div
className={classes[`FullServices__parent-${active}`]}
onClick={() => activeHandler()}
>
Кузов
</div>
This way seemed to me very uncomfy and not universal. Furthermore I will refactor it all using redux-toolkit
initial state
expanded
There are many ways to use accordion menus
Add following code in src/App.js
import React from 'react';
const App = () => {
const accordionData = {
title: 'Section 1',
content: `Lorem ipsum dolor, sit amet consectetur adipisicing elit. Quis sapiente
laborum cupiditate possimus labore, hic temporibus velit dicta earum
suscipit commodi eum enim atque at? Et perspiciatis dolore iure
voluptatem.`
};
const { title, content } = accordionData;
return (
<React.Fragment>
<h1>React Accordion Demo</h1>
<div className="accordion">
<div className="accordion-item">
<div className="accordion-title">
<div>{title}</div>
<div>+</div>
</div>
<div className="accordion-content">{content}</div>
</div>
</div>
</React.Fragment>
);
};
export default App;
I'm trying to change the single select box to multiple select. I changed the select to include multiple, but when I click multiple selections, none of the markers show up on the Google Map. I'm struggling with how to bind the selections to the sites array that contain the locations. How can Implement a multi select box within the code?
Index.html
<!DOCTYPE html>
<html>
<head>
<title>Map</title>
<meta http-equiv="X-UA-Compatible"content="IE=Edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1, minimum-scale=1">
<meta charset="utf-8">
<link rel="stylesheet" href="CSS/bootstrap.min.css">
<link rel="stylesheet" href="CSS/style.css">
</head>
<div ng-app="mapsApp" ng-controller="MapCtrl">
<div align ="center" class ="input-w">
<div class ="gulf">States</div>
<fieldset>
<div class = "flexi">
<label>ISE: </label>
<select id ="ISEs" multiple class="dropdown" name="singleSelect" ng-model="data.singleSelect" ng-change="filterMarkers(); centerMap()">
<option value="0">All</option>
<option value="Bob">Bob</option>
<option value="Sally">Sally</option>
</select><br><br>
</div>
</div>
</fieldset>
</div>
<div id="map"></div>
{{marker.title}}
</div>
</div>
<!--
<script src="js/jquery.min.js"></script> -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/slim-select/1.25.0/slimselect.min.js"></script>
<script src="https://code.jquery.com/jquery-3.4.1.min.js" integrity="sha256-CSXorXvZcTkaix6Yvo6HppcZGetbYMGWSFlBw8HfCJo=" crossorigin="anonymous"></script>
<script async defer src="https://maps.googleapis.com/maps/api/js?key=myKey"onerror = "googleError()"
></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.7.8/angular.min.js"></script>
<script src="js/app.js"></script>
</body>
</html>
App.JS
var sites= [
{name:"ABC",address:"123",lat:"29.97046",lng:"-92.09689",SalesPerson:"Bob"},
{name:"DEF",address:"123",lat:"30.97046",lng:"-92.09689",SalesPerson:"Bob"},
{name:"GHI",address:"123",lat:"31.97046",lng:"-92.09689",SalesPerson:"Sally"},
{name:"JKL",address:"123",lat:"32.97046",lng:"-92.09689",SalesPerson:"Sally"},
];
//Angular App Module and Controller
angular.module('mapsApp', [])
.controller('MapCtrl', function ($scope) {
var mapOptions = {
zoom: 7,
center: new google.maps.LatLng(32.340803,-89.4855946),
mapTypeId: google.maps.MapTypeId.ROADMAP
}
$scope.map = new google.maps.Map(document.getElementById('map'), mapOptions);
$scope.markers = [];
var infoWindow = new google.maps.InfoWindow();
var icons = {
Bob: {
icon: {
url: "http://maps.google.com/mapfiles/ms/icons/green-dot.png"
}
},
Sally: {
icon: {
url: "http://maps.google.com/mapfiles/ms/icons/red-dot.png"
}
}
}
var createMarker = function (info) {
var features = [
{
position: new google.maps.LatLng(info.lat,info.lng),
type: info.SalesPerson
}
]
for (var i =0; i < features.length; i++)
var marker = new google.maps.Marker({
map: $scope.map,
position: features[i].position,
icon:icons[features[i].type].icon,
title: info.name,
});
marker.content = '<div class="iw-ISE">' + info.ISE + '</div>'
+ '<div class="iw-labels">' + "Contact: "+ info.Contact + '</div>'
+ '<div class="iw-labels">' + "Store Phone: "+ info.Phone + '</div>'
+'<p>'+ info.address +'</p>'
google.maps.event.addListener(marker, 'click', function () {
infoWindow.setContent('<h2 class ="title">' + marker.title + '</h2>' + marker.content);
infoWindow.open($scope.map, marker);
});
$scope.markers.push(marker);
}
for (i = 0; i < sites.length; i++) {
createMarker(sites[i]);
}
$scope.openInfoWindow = function (e, selectedMarker) {
e.preventDefault();
google.maps.event.trigger(selectedMarker, 'click');
}
$scope.clearMarkers = function() {
for (var i = 0; i < $scope.markers.length; i++) {
$scope.markers[i].setMap(null);
}
$scope.markers.length = 0;
}
$scope.filterMarkers = function() {
//1.select filtered cities
var filteredISE;
var ISEName = $scope.data.singleSelect;
if(ISEName == '0') {
filteredISE = sites;
}
else {
filteredISE = sites.filter(function(c){
if(c.SalesPerson == ISEName)
return c;
});
}
//2.update markers on map
$scope.clearMarkers();
for (i = 0; i < filteredISE.length; i++) {
createMarker(filteredISE[i]);
}
}
}
});
I re-wrote my pen with Angular Js, here is the link codepen.io/ueple/full/ExjaXjL , tell me if it's ok for you ?, or is there's something I've missed ! :-)
After reading your scope, I create an example in Js, not Angularjs like, but with some functionalities you're expecting, I hope so. Tell me if it helps you.
My codePen
What i'm using is an Array of Places and Markers that are read with the function
initalizeMaps.
var mapPlaces = {
id1: {town: 'Decines Charpieu', lat: 45.767000, lng: 4.950000, zoom: 14, display: 1},
id2: {town: 'Paris', lat: 48.851208, lng: 2.348436, zoom: 10, display: 2},
id3: {town: 'New York', lat: 40.748294, lng: -73.985858, zoom: 11, display: 1},
id4: {town: 'Rio de Janeiro', lat: -22.974772, lng: -43.185066, zoom: 8, display: 2},
id5: {town: 'City of Athena', lat: 37.980549, lng: 23.725121, zoom: 10, display: 1}
};
and
var mapMarkers = [
{id: 1,title: 'My town', desc: 'A town of 25000 inhabitants', lat: 45.768811, lng: 4.955300, icon: 'reddot', extraTitle: 'My town Extra Infos', extraDesc: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. In tempor ante ante. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Aenean commodo mi nec nisl cursus mollis. Nam tortor elit, suscipit vitae tellus at, suscipit pretium metus. Aenean id ultrices ligula. In non dui et magna placerat semper ut et tellus. Ut purus nulla, malesuada a ante malesuada, rhoncus vulputate diam.', url: "https://www.decines-charpieu.fr/uploads/Image/41/IMF_DIAPORAMA_ACCUEIL/GAB_REFONTE/6313_606_Ville-Cuturel.jpg"}];
And the function to read those 2 Arrays is
function initializeMap(idMap)
google.maps.event.addDomListener(window, 'load', initializeMap( currentMap ));
Regards
Let me explain the situation. Currently I am doing a project to practice SCSS and React. It is a website dedicated to soccer team. The problem is that I am creating a custom modal window using CSS and HTML. What I want is that whenever I click the button "see pics" a modal window related to this card should open, while in my case all modal windows open at once.
All modal windows open at once stacked one on each other. Like that.
There are four modal windows like that overall, but only the top modal shows.
The HTML structure of these modal windows is the following:
They have got the same classes and ids.
In React part I have a component called PopUp, which gets information from db.json as props.
import React from 'react';
import Button from './button-round-dark';
const generateAdditionalInfo = ({info}) => {
if (info) {
return info.map((item) => {
const addInfo = item.additionalInfo;
console.log(addInfo);
return (
<div className="popup" id="popup">
<div className="popup__content" key={addInfo.id}>
<div className="popup__left">
<img className="popup__img" src={`../../${process.env.PUBLIC_URL}/images/additionalInfoPics/${addInfo.images[0]}`}/>
<img className="popup__img" src={`../../${process.env.PUBLIC_URL}/images/additionalInfoPics/${addInfo.images[1]}`}/>
</div>
<div className="popup__right">
x
<h2 className="heading-secondary u-margin-bottom-small">{addInfo.title}</h2>
<p className="popup__description">{addInfo.description}</p>
</div>
</div>
</div>
)
})
}
}
const PopUp = (props) => {
return (
<div>
{generateAdditionalInfo(props)}
</div>
)
}
export default PopUp;
db.json
"legendaryTeam":[
{
"id":"p1",
"name": "buffon",
"image":"buffon.jpg",
"years":"2001-2018",
"number":"18",
"position":"goalkeeper",
"physicalFeatures":{
"weight":"86",
"height":"194",
"speed":"7",
"power":"250"
},
"additionalInfo":{
"id":"1",
"images":["buffon_1.jpg","buffon_2.jpg"],
"title":"Buffon title",
"description":"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Etiam dignissim diam quis enim lobortis scelerisque. Egestas tellus rutrum tellus pellentesque eu tincidunt tortor aliquam nulla. Lorem sed risus ultricies tristique nulla aliquet enim. Ultrices in iaculis nunc sed augue lacus viverra vitae congue."
}
},
{
"id":"p2",
"name": "Ravanelli",
"image":"ravanelli.jpg",
"years":"1992-1996",
"number":"10",
"position":"forward",
"physicalFeatures":{
"weight":"75",
"height":"176",
"speed":"9",
"power":"300"
},
"additionalInfo":{
"id":"2",
"images":["ravanelli_1.jpg","ravanelli_2.jpg"],
"title":"Ravanelli title",
"description":"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Etiam dignissim diam quis enim lobortis scelerisque. Egestas tellus rutrum tellus pellentesque eu tincidunt tortor aliquam nulla. Lorem sed risus ultricies tristique nulla aliquet enim. Ultrices in iaculis nunc sed augue lacus viverra vitae congue."
}
}
Please pay attention to additionalInfo object, it is where information goes to PopUp component.
Custom CSS code for modal window looks like this.
.popup {
height: 100vh;
width:100%;
position:fixed;
top:0;
left:0;
background-color: rgba($color-black,0.8);
z-index:99999;
opacity: 0;
visibility: hidden;
transition:all .3s;
&:target {
opacity: 1;
visibility: visible;
}
&__content {
#include centrify;
width:75%;
background-color: $color-white;
box-shadow: 0 2rem 4rem rgba($color-black, .2);
border-radius: 3px;
display: table;
overflow: hidden;
}
&__left {
width:33.33333333%;
display: table-cell;
}
&__right {
width:66.666666666%;
display: table-cell;
vertical-align: middle;
padding: 3rem 5rem;
}
&__img {
display: block;
width:100%;
}
&__description {
font-size: 1.4rem;
margin-bottom: 4rem;
}
}
Modal window open with help of target selector. Now I am scratching head over how to make implement what I want. Please help me out. Do you have any ideas?
By the way other modal windows look like this. But they are lower in stack so they are not shown.
If you want to tinker with my project click here
To run react see picture below
To run db.json you need to install it globally
$ npm install -g json-server
And then run it, see pic below
To run SCSS see pic below
Your problem is not in your description, you bind the ButtonRoundDark to all of the modal. You need to add onClick event to your 'see pics' button. After click, fetch the data, show the modal.
I am adding a readmore directive to an angular app. The read-more works great, but try to use a filter for text and it does not interpret the filter string correctly.
Example: http://plnkr.co/edit/Tsqkv1nd6CC8e5Kr9pdU?p=preview
Change demo text to the code below to see what is happening:
<p read-more>(1) This is a short paragraph.</p>
<p read-more>(2) This is a long paragraph. This is a long paragraph. This is a long paragraph. This is a long paragraph. This is a long paragraph. This is a long paragraph. This is a long paragraph. This is a long paragraph. This is a long paragraph. This is a long paragraph.</p>
<p>(3) {{desc}}</p>
<p read-more>(4) {{desc}}</p>
Notice the 3rd and 4th examples use the $scope.desc value defined in the controller in app.js. #3 works. #4 fails. Why? How to fix?
app.js:
var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope) {
$scope.desc = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec rutrum vehicula tortor, vitae ornare nunc semper eu. Vivamus varius, eros vel tristique accumsan, libero nulla cursus ante, eu eleifend risus orci scelerisque nibh. Curabitur feugiat, augue ut commodo bibendum, nisi leo porttitor diam, tincidunt auctor tellus ante sit amet nibh. Duis velit libero, aliquam at felis eu, pellentesque mollis mi. Nam a est orci. Ut bibendum sagittis semper. Cras eget arcu non augue mollis aliquam. Ut ut gravida ligula. Nulla imperdiet lacinia mi, nec fringilla mauris interdum at. Phasellus gravida tempor varius. Cras molestie et nulla eget maximus. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris aliquet malesuada feugiat. Curabitur fermentum bibendum nulla, non dictum ipsum tincidunt non. Quisque convallis pharetra tempor. Donec id pretium leo. Pellentesque luctus massa non elit viverra pellentesque. Cras vitae neque molestie, rhoncus ipsum sit amet, lobortis dui. Fusce in urna sem. Vivamus vehicula dignissim augue et scelerisque. Etiam quam nisi, molestie ac dolor in, tincidunt tincidunt arcu. Praesent sed justo finibus, fringilla velit quis, porta erat. Donec blandit metus ut arcu iaculis iaculis. Cras nec dolor fringilla justo ullamcorper auctor. Aliquam eget pretium velit. Morbi urna justo, pulvinar id lobortis in, aliquet placerat orci.';
});
app.directive('readMore', function() {
return {
restrict: 'A',
transclude: true,
replace: true,
template: '<p></p>',
scope: {
moreText: '#',
lessText: '#',
words: '#',
ellipsis: '#',
char: '#',
limit: '#',
content: '#'
},
link: function(scope, elem, attr, ctrl, transclude) {
var moreText = angular.isUndefined(scope.moreText) ? ' <a class="read-more">Read More...</a>' : ' <a class="read-more">' + scope.moreText + '</a>',
lessText = angular.isUndefined(scope.lessText) ? ' <a class="read-less">Less ^</a>' : ' <a class="read-less">' + scope.lessText + '</a>',
ellipsis = angular.isUndefined(scope.ellipsis) ? '' : scope.ellipsis,
limit = angular.isUndefined(scope.limit) ? 150 : scope.limit;
attr.$observe('content', function(str) {
readmore(str);
});
transclude(scope.$parent, function(clone, scope) {
readmore(clone.text().trim());
});
function readmore(text) {
var text = text,
orig = text,
regex = /\s+/gi,
charCount = text.length,
wordCount = text.trim().replace(regex, ' ').split(' ').length,
countBy = 'char',
count = charCount,
foundWords = [],
markup = text,
more = '';
if (!angular.isUndefined(attr.words)) {
countBy = 'words';
count = wordCount;
}
if (countBy === 'words') { // Count words
foundWords = text.split(/\s+/);
if (foundWords.length > limit) {
text = foundWords.slice(0, limit).join(' ') + ellipsis;
more = foundWords.slice(limit, count).join(' ');
markup = text + moreText + '<span class="more-text">' + more + lessText + '</span>';
}
} else { // Count characters
if (count > limit) {
text = orig.slice(0, limit) + ellipsis;
more = orig.slice(limit, count);
markup = text + moreText + '<span class="more-text">' + more + lessText + '</span>';
}
}
elem.append(markup);
elem.find('.read-more').on('click', function() {
$(this).hide();
elem.find('.more-text').addClass('show').slideDown();
});
elem.find('.read-less').on('click', function() {
elem.find('.read-more').show();
elem.find('.more-text').hide().removeClass('show');
});
}
}
};
});
style.css:
/* Put your css in here */
a.read-more, a.read-less {
cursor: pointer;
color: blue;
font-size: 0.8em;
}
span.more-text {
display: none;
}
span.more-text.show {
display: inline !important
}
index.html:
<!DOCTYPE html>
<html ng-app="plunker">
<head>
<meta charset="utf-8" />
<title>Angular Read More Directive</title>
<script>
document.write('<base href="' + document.location + '" />');
</script>
<link rel="stylesheet" href="style.css" />
<script data-require="jquery" data-semver="2.1.1" src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script data-require="angular.js#1.3.x" src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.3.7/angular.js" data-semver="1.3.7"></script>
<script src="app.js"></script>
</head>
<body ng-controller="MainCtrl">
<p read-more>This is a short paragraph.</p>
<p read-more>This is a long paragraph. This is a long paragraph. This is a long paragraph. This is a long paragraph. This is a long paragraph. This is a long paragraph. This is a long paragraph. This is a long paragraph. This is a long paragraph. This is a long paragraph.</p>
<p read-more>{{desc}}</p>
</body>
</html>
As per your current code implementation readmore is getting called before the transcluded DOM content gets projected on directive template.
In this case you should take use content attribute just by saying content="{{desc}}", which will allow to call readmore method of directive as attr.$observe method will get fired.
<p read-more content="{{desc}}">(4)</p>
Demo Plunkr
I am confused about how to show an .active class on a clicked item when using the ng-repeat directive. Here's a Plunker.
Here's my view:
<h4>Arctic Videos</h4>
<ul class="list-unstyled">
<li class="clearfix" ng-repeat="item in videos" ng-class="{ active: $index }" style="padding-bottom: 2em;">
<div style="float: left; position:relative;">
<img class="img-thumbnail" ng-src="{{item.thumbUrl}}" width="100" height="68" alt="">
</div>
<h4>{{item.title}}</h4>
</li>
</ul>
My script.js
var ArcticApp = angular.module('ArcticApp', ['ngRoute', 'ngSanitize']);
ArcticApp.config(function($routeProvider){
$routeProvider
.when('/', {
templateUrl: './partials/map.html',
controller: 'MainController'
})
.when('/videos/:itemId', {
templateUrl: './partials/videos.html',
controller: 'VideoController'
})
.otherwise({
redirectTo: '/'
})
});
ArcticApp.controller('MainController', function($scope){
$scope.message = "This is the map page!";
});
ArcticApp.controller('VideoController', function($scope, $routeParams, $sce){
$scope.videos = [
{
"blockquote": "et sint quae\nqui odio fugit quia aut modi id maxime\nsequi qui et",
"title": "Canada",
"synopsis": "<p>Some text will go here and there. Some more will go here.</p><p>Yet even some more text will go here and there. yes, tehre's even more here.</p>",
"id": 897,
"thumbUrl": "http://placehold.it/100x68"
},
{
"blockquote": "sit molestiae possimus ut in explicabo\nea autem saepe a iusto est exercitationem at\ndistinctio quia consectetur nulla vel maxime",
"title": "USA",
"synopsis": "<p>Some text will go here and there. Some more will go here.</p><p>Yet even some more text will go here and there. yes, tehre's even more here.</p>",
"id": 471,
"thumbUrl": "http://placehold.it/100x68"
},
{
"blockquote": "recusandae natus minus est saepe alias\nvero amet quia natus voluptatem ut saepe dolor rem\nperspiciatis quia unde quia cum aliquam sint",
"title": "Russia",
"synopsis": "<p>some text can go here </p>",
"id": 400,
"thumbUrl": "http://placehold.it/100x68"
}
];
$scope.whichItem = $routeParams.itemId;
$scope.trustAsHtml = $sce.trustAsHtml.bind($sce);
});
How would I go about assigning an active class to a clicked item?
Use
ng-class="{ active: selectedVideo === item }"
And
ng-click="selectVideo(item)"
In the controller, add
$scope.selectVideo = function(video) {
$scope.selectedVideo = video;
}
you can use it like this
<li class="clearfix" ng-repeat="(key,item) in videos" ng-class="{ active:(condition) }" style="padding-bottom: 2em;">
key is the number of iteration and condition can be any Boolean logic to make active class true
like
ng-class="{ active: 1==1 }
in this case since 1==1 is true so active class will be printed .