My code is as shown below:
xyz.html
<div class="q-filters" sticky offset="25">
<a style="text-decoration:none;margin-bottom:10px;color:black;" href="" ng-click="gotoDiv(menu.name)" style="margin-bottom:10px;" ng-repeat="menu in menuItems" class='q-filter q-recommended'>{{menu.name}}</a>
</div>
<div class="q-menu" ng-repeat="menu in menuItems" ng-if="menu.isVisible">
<div id="anchor{{menu.name}}" class="q-head anchor"><span>{{menu.name}}</span></div>
<div class="q-list" ng-repeat="item in menu.items" ng-class="{'active':item.addClicked}">
</div>
xyz.js
$scope.gotoDiv = function(x) {
var newHash = 'anchor' + x;
if ($location.hash() !== newHash) {
$location.hash('anchor' + x);
} else {
$anchorScroll();
}
};
I have followed the code given here
But somehow it does not land to the div perfectly. For more details the demo is shown here
Now, how to make it work?
Related
I am pretty close to having this app finished, but have one last hurdle. I am dynamically populating tabs and data via the WordPress Rest API and when I only had 2 tabs it worked wonderfully, but when I added tab 3 and 4 I ran into issues. When I click tabs 2-4 all tabs receive the "active" class instead of just the one that was clicked; thus also all 3 tabs content data also displays.
Here is the code:
var homeApp = angular.module('homeCharacters', ['ngSanitize']);
homeApp.controller('characters', function($scope, $http) {
$scope.myData = {
tab: 0
}; //set default tab
$http.get("http://bigbluecomics.dev/wp-json/posts?type=character").then(function(response) {
$scope.myData.data = response.data;
});
});
homeApp.filter('stripTags', function() {
return function(text) {
return text ? String(text).replace(/<[^>]+>/gm, '') : '';
};
});
<section class="characters" ng-app="homeCharacters" ng-controller="characters as myData">
<div class="char_copy">
<h3>Meet the Characters</h3>
<div class="char_inject" ng-repeat="item in myData.data" ng-show="myData.tab === item.menu_order">
<div class="copy_wrap">
<h3>{{ item.acf.team }}:</h3>
<h2>{{ item.acf.characters_name }} <span>[{{item.acf.real_name}}]</span></h2>
<p class="hero_type">{{ item.acf.hero_type }}</p>
<div class="description" ng-repeat="field in item.acf.character_description">
<p>{{field.description_paragraph}}</p>
</div>
Learn More
</div>
<div class="image_wrap">
<img src="{{ item.acf.homepage_full_image.url }}" />
</div>
</div>
</div>
<div class="char_tabs">
<nav>
<ul ng-init="ch.tab = 0">
<li class="tab" ng-repeat="item in myData.data" ng-class="{'active' : item.menu_order == myData.tab}">
<a href ng-click="myData.tab = item.menu_order">
<img src="{{ item.featured_image.source }}" />
<div class="tab_title_wrap">
<h3>{{ item.acf.characters_name }}</h3>
</div>
</a>
</li>
</ul>
</nav>
</div>
</section>
I would love any ideas! Thanks!
The code seems to work, see Fiddle. What are the values of menu_order? If they are the same for cases 2-4, then that would explain the behaviour.
var app = angular.module("myDiscuss", []);
app.controller("TabController", function() {
this.tab = 0;
this.subTab = 0;
this.like = 0;
this.selectLike = function(setTab) {
this.like= setTab;
};
this.selectTab = function(setTab) {
this.tab= setTab;
};
this.selectSubTab = function(setTab){
this.subTab = setTab;
};
this.isSelected = (function(checkTab){
return this.tab === checkTab;
});
this.isSelectedSub = (function(checkTab){
return this.subTab === checkTab;
});
this.isSelectedLike = (function(checkTab) {
return this.like === checkTab;
});
});
app.controller('FormController', function($scope) {
$scope.person = {
name: null
};
$scope.people = [];
$scope.submit = function() {
if ($scope.person.name) {
$scope.people.push({name: $scope.person.name});
$scope.person.name = '';
}
};
});
app.directive('replyBox', function(){
return {
restrict:'A',
templateUrl:'../templates/reply-box.html'
};
});
app.directive ('commentSection', function(){
return {
restrict:'A',
scope :{},
templateUrl:'../templates/comment-section.html'
};
});
<body ng-app="myDiscuss">
<div class="container">
<div class="row">
<div>
<div class="thumbnail" ng-controller="TabController as tabs">
<div ng-show="tabs.isSelectedLike(1)">
</div>
<section class="caption">
<ul class="nav nav-pills">
<li ng-class="{ active:like === 1 }" >
<a href ng-click="tabs.selectLike(1)">Helpful</a>
</li>
<li ng-class= "{ active:tab === 2 }">
<a href ng-click="tabs.selectTab(2)">Comment</a>
</li>
</ul>
<div comment-section ng-show="tabs.isSelected(2)"></div>
</section>
</div>
</div>
</div>
</div>
</body>
<!--comment-section.html-->
<div class="panel" >
<form ng-submit="submit()" ng-controller="FormController">
<blockquote ng-repeat="(index,object) in people" >
<ul class="nav nav-pills">
<li ng-class="{ active:subTab === 3 }" >
<a href ng-click="tabs.selectSubTab(3)">Helpful</a>
</li>
<li ng-class= "{ active:subTab === 4}">
<a href ng-click="tabs.selectSubTab(4)">Reply</a>
</li>
</ul>
<div reply-box ng-show="tabs.isSelectedSub(4)"></div>
</blockquote>
<input type="text" ng-model="person.name" name="person.name" />
</form>
</div>
<!-- reply-box.html -->
<div>
<input type="text">
</div>
When I add the reply-box directive to the comment-section directive it does not perform the 'submit' action. When the "reply" link in the commentSection directive is clicked, the ng-show directive does not working for the reply-box directive.
Well I don't see any input type='submit' in your code, maybe thats why ng-submit is not working,
Moreover i think your ng-show directive isn't working because the ng-controller="TabController as tabs" ends here
<div class="thumbnail" ng-controller="TabController as tabs">
<div ng-show="tabs.isSelectedLike(1)">
</div>
<section class="caption" >
<ul class="nav nav-pills">
<li ng-class="{ active:like === 1 }" >
<a href ng-click="tabs.selectLike(1)">Helpful</a>
</li>
<li ng-class= "{ active:tab === 2 }">
<a href ng-click="tabs.selectTab(2)">Comment</a>
</li>
</ul>
<div comment-section ng-show="tabs.isSelected(2)"></div>
</section>
</div>
Thus you are calling your ng-show="tabs.isSelectedSub(4)" wont return any thing because this method is not defined in your FormController.
Hope it helps.
The errors occur because the scope for the comment section directive does not inherit from the parent scope.
Define a scope that inherits from the parent scope
To inherit from the parent scope, you'll need to set the scope property of the comment-section directive to true.
From the AngularJS documentation:
scope: true - the directive creates a new child scope that prototypically inherits from the parent scope. If more than one directive (on the same DOM element) requests a new scope, only one new child scope is created. Since we have "normal" prototypal inheritance, this is like ng-include and ng-switch, so be wary of 2-way data binding to parent scope primitives, and child scope hiding/shadowing of parent scope properties.
The comment-section directive can be rewritten thus:
app.directive ('commentSection', function(){
return {
restrict:'A',
scope :true,
templateUrl:'../templates/comment-section.html'
};
});
When I run the function in the browser, "[object Object]" shows up instead of the text stored inside the variable $new_comment. I wish to append user inputs.
HTML :
<li class="list-group-item">"User comments"</li>
<div class="comments">
<ul class="list-group"></ul>
</div>
Js :
var addCommentFromInputBox = function() {
var $new_comment;
if ($(".input-group input").val() !== "") {
$new_comment = $("<p>").text($(".input-group input").val());
$new_comment.hide();
$(".list-group").append('<li class="list-group-item">' + ($new_comment) + '</li>');
$new_comment.fadeIn();
$(".input-group input").val("");
}
};
Everything runs fine when I change the code to:
$(".list-group").append($new_comment);
But I wish to style it with Bootstrap.
You can use it something like this $(".list-group").append($('<li class="list-group-item"></li>').html($new_comment));
Here this the full demo code
addCommentFromInputBox = function() {
var $new_comment;
if ($(".input-group input").val() !== "") {
$new_comment = $("<p>").text($(".input-group input").val());
$new_comment.hide();
$(".list-group").append($('<li class="list-group-item"></li>').html($new_comment));
$new_comment.fadeIn();
$(".input-group input").val("");
}
}
addCommentFromInputBox();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="comments">
<ul class="list-group">
</ul>
</div>
var listGroupItem = $('<li class="list-group-item"></li>').html($new_comment)
$(".list-group").append($listGroupItem);
I have a list that when you click on an li, it reveals a hidden list of information about that person.
In the footer, theres simple navigation showing the different views and when you click, angular filters through the original list for the matched elements.
All I am stuck on is this;
if you click an li element and reveal the info for that person, then click one of the navigation buttons, it will still show that person but with the hidden element revealed...not closed.
Ideally, id prefer that when the user clicks any of the footer navigation buttons, the list reveals just the names, not the hidden info..regardless of whether it was clicked or not.
If this was just in Jquery or javascript, i would know how to approach this but, Im sure theres an 'angular specific' approach I just don't know about.
Heres the HTML:
<div ng-controller="MyCtrl">
<ul id="housewrapper" ng-cloak>
<li ng-repeat="item in house track by item.member" class="listings" ng-click="showComments = !showComments;" ng-show="([item] | filter:filters).length > 0" >
<span ng-if="item.whereHesheStands == 'oppose'"><img class="dot againstdot" src="img/against.png">{{item.member}}
</span>
<span ng-if="item.whereHesheStands == 'leanoppose'">
<img class="dot againstdot" src="img/against.png">{{item.member}}
</span>
<span ng-if="item.whereHesheStands == 'support'" ng-click="clickMeImg($event);">
<img class="dot supportdot" src="img/support.png">{{item.member}}
</span>
<span ng-if="item.whereHesheStands == 'leansupport' ">
<img class="dot supportdot" src="img/support.png">{{item.member}}
</span>
<span ng-if="item.whereHesheStands == 'unknown' ">
<img class="dot undecideddot" src="img/undecided.png">{{item.member}}
</span>
<span ng-if="item.whereHesheStands == 'undecided' ">
<img class="dot undecideddot" src="img/undecided.png">{{item.member}}
</span>
<div class="memberdetail" ng-show="showComments" ng-click="$event.stopPropagation();" >
<ul class="memberbreakdown">
<li class="partyline" >
{{item.party}} - {{item.state}}</li>
<li class="comments">
<span style="color:#a4a4a4;" ng-if="!(item.comments)">Comment not available</span>
<span>{{item.comments}}</span>
</li>
</ul>
</div>
</li>
</ul>
<div id="appfooterWrapper">
<ul id="appfooter">
<li ng-click="myFunctionRepublican();" ng-class="class">R</li>
<li ng-click="myFunctionDemocrat();" ng-class="class2">D</li>
<li ng-click="myFunctionSupport();" ng-class="class3">S</li>
<li ng-click="myFunctionOppose();" ng-class="class4">A</li>
<li ng-click="myFunctionUnknown();" ng-class="class5">U</li>
</ul>
</div>
and the javascript of the "R" navigation button
$scope.myFunctionRepublican = function() {
$('.memberdetail').removeClass('ng-show');
$('.memberdetail').bind('click');
$scope.filters = function(house) {
return house.party == 'R' ;
};
if ($scope.class === ""){
$scope.class = "rep";
$scope.class2 = "";
$scope.class3 = "";
$scope.class4 = "";
$scope.class5 = "";
}
else{
$scope.class = "";
}
$('html, body').animate({scrollTop:0}, 'fast');
var loading;
loading = true;
if (loading == true) {
setTimeout(function() {
spinner.stop();
$('.listings').not('.ng-hide').addClass('republican');
console.log($('.republican').length);
$('#housewrapper').stop().fadeIn(350).addClass(
'marginAdd');
$('#subhead').removeClass('slidedown');
$('#subhead').html('Republicans').css('color', '#d41600');
setTimeout(function() {
$('#subhead').addClass('slidedown');
}, 300);
}, 500);
}
}
Here's the Fiddle
A couple changes, attach a property onto each member.
View changes:
ng-click="item.showComments = !item.showComments;"
<div class="memberdetail" ng-show="item.showComments" ng-click="$event.stopPropagation();" >
Controller changes:
function resetShow() {
for(var i = 0, l = $scope.house.length; i < l; i++) {
$scope.house[i].showComments = false;
}
}
Then just call it when you navigate:
$scope.myFunctionUnknown = function() {
resetShow();
....
Forked Fiddle
I'm trying to keep track of the selected tab in the view model but I can't seem to make it work.
In the following code when you click a tab the header will update correctly but the content of the tab is not displayed. If you remove , click: $parent.selectSection then the contents are shown but the header does not update.
Now if you remove the data-bind="css: { active: selected }" from the li then it seems to work when you click the tabs but the button to select the second tab doesn't.
How can I make this work?
See: http://jsfiddle.net/5PgE2/3/
HTML:
<h3>
<span>Selected: </span>
<span data-bind="text: selectedSection().name" />
</h3>
<div class="tabbable">
<ul class="nav nav-tabs" data-bind="foreach: sections">
<li data-bind="css: { active: selected }">
<a data-bind="attr: { href: '#tab' + name }
, click: $parent.selectSection" data-toggle="tab">
<span data-bind="text: name" />
</a>
</li>
</ul>
<div class="tab-content" data-bind="foreach: sections">
<div class="tab-pane" data-bind="attr: { id: 'tab' + name }">
<span data-bind="text: 'In section: ' + name" />
</div>
</div>
</div>
<button data-bind="click: selectTwo">Select tab Two</button>
JS:
var Section = function (name) {
this.name = name;
this.selected = ko.observable(false);
}
var ViewModel = function () {
var self = this;
self.sections = ko.observableArray([new Section('One'),
new Section('Two'),
new Section('Three')]);
self.selectedSection = ko.observable(new Section(''));
self.selectSection = function (s) {
self.selectedSection().selected(false);
self.selectedSection(s);
self.selectedSection().selected(true);
}
self.selectTwo = function() { self.selectSection(self.sections()[1]); }
}
ko.applyBindings(new ViewModel());
There are several ways that you can handle this either using bootstrap's JS or by just having Knockout add/remove the active class.
To do this just with Knockout, here is one solution where the Section itself has a computed to determine if it is currently selected.
var Section = function (name, selected) {
this.name = name;
this.isSelected = ko.computed(function() {
return this === selected();
}, this);
}
var ViewModel = function () {
var self = this;
self.selectedSection = ko.observable();
self.sections = ko.observableArray([
new Section('One', self.selectedSection),
new Section('Two', self.selectedSection),
new Section('Three', self.selectedSection)
]);
//inialize to the first section
self.selectedSection(self.sections()[0]);
}
ko.applyBindings(new ViewModel());
Markup would look like:
<div class="tabbable">
<ul class="nav nav-tabs" data-bind="foreach: sections">
<li data-bind="css: { active: isSelected }">
<a href="#" data-bind="click: $parent.selectedSection">
<span data-bind="text: name" />
</a>
</li>
</ul>
<div class="tab-content" data-bind="foreach: sections">
<div class="tab-pane" data-bind="css: { active: isSelected }">
<span data-bind="text: 'In section: ' + name" />
</div>
</div>
</div>
Sample here: http://jsfiddle.net/rniemeyer/cGMTV/
There are a number of variations that you could use, but I think that this is a simple approach.
Here is a tweak where the active tab used the section name as a template: http://jsfiddle.net/rniemeyer/wbtvM/