Angular - toggle class, text, and scroll in controller using ngclick - html

I have been rewriting some Jquery tasks that I had previously written and want them to now work in my AngularJs App.
I am able to toggle the glyphicons, but how can I change the text and scroll feature as well?
This is my code:
HTML
<body ng-app="toggleApp" ng-controller="toggleCtrl as tc">
<a ng-click="tc.toggle('glyph'); tc.toggle('text')" class="lead p-color learn-button togglebtn shake shake-rotate">
<small>
<span id="toggleGlyph" ng-class="tc.iconGlyph ? 'glyphicon glyphicon-minus' : 'glyphicon glyphicon-plus'">
</span> <span ng-class="tc.textDesc ? 'Hide' : 'Learn More'">Learn More</span>
</small>
</a>
</body>
Main Javascript
var app = angular.module('app', ['ui.bootstrap', 'ngRoute', 'ngAnimate']);
app.config(function($interpolateProvider, $routeProvider) {
$interpolateProvider.startSymbol('[[');
$interpolateProvider.endSymbol(']]');
$routeProvider
.when('/', {
templateUrl : 'pages/LandingPage.html',
controller : 'LandingCtrl'
})
Controller Javascript
app.controller('toggleCtrl', function () {
this.toggle = function (property) {
this.iconGlyph = (property === 'glyph') ? !this.iconGlyph : this.iconGlyph;
this.textDesc = (property === 'text') ? !this.textDesc : this.textDesc;
}
});
Previous Jquery
$(function () {
$('a.togglebtn').click(function () {
$("#toggleGlyph").toggleClass("glyphicon-minus glyphicon-plus");
$('#toggleText').text($('#toggleText').text() === "Learn More" ? "Hide" : "Learn More");
$('#myContent').stop().slideToggle(500);
$('html,body').animate({ scrollTop: $('#myContent').offset().top - 200 }, 800);
return false;
});
});
http://jsfiddle.net/amptwig91/7jf5sdnv/

check this snippet
var app = angular.module("app", []);
app.controller('toggleCtrl', function() {
var _parent = this;
this.toggle = function() {
_parent.isToggled = !_parent.isToggled;
setText();
}
function setText() {
if (_parent.isToggled) {
_parent.text = 'Hide';
} else {
_parent.text = 'Learn More';
}
}
this.isToggled = false;
this.text = 'Learn More';
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css">
<body ng-app="app" ng-controller="toggleCtrl as _">
<i class="fa" ng-class="{'fa-plus' : !_.isToggled , 'fa-minus' : _.isToggled }"></i> {{_.text}}
<body>

Since I am using UI-Bootstrap. This is how I ended up solving it!
<a class="lead p-color learn-button togglebtn shake shake-rotate" data-ng-init="isCollapsed1 = true" data-ng-click="isCollapsed1 = !isCollapsed1">
<small>
<div ng-show="isCollapsed1">
<span class="glyphicon glyphicon-plus" ></span> Learn More
</div>
<div ng-hide="isCollapsed1">
<span class="glyphicon glyphicon-minus"></span> Hide
</div>
</small>
</a>

Related

Swipe to Reveal is not working

I have implemented a swipe to reveal Oracle JET component.
Below is my Js code
this.action = ko.observable("No action taken yet");
this.handleReady = function()
{
// register swipe to reveal for all new list items
$("#listview").find(".item-marker").each(function(index)
{
var item = $(this);
var id = item.prop("id");
var startOffcanvas = item.find(".oj-offcanvas-start").first();
var endOffcanvas = item.find(".oj-offcanvas-end").first();
// setup swipe actions
oj.SwipeToRevealUtils.setupSwipeActions(startOffcanvas);
oj.SwipeToRevealUtils.setupSwipeActions(endOffcanvas);
// make sure listener only registered once
endOffcanvas.off("ojdefaultaction");
endOffcanvas.on("ojdefaultaction", function()
{
self.handleDefaultAction(item);
});
});
};
this.handleDestroy = function()
{
// register swipe to reveal for all new list items
$("#listview").find(".item-marker").each(function(index)
{
var startOffcanvas = $(this).find(".oj-offcanvas-start").first();
var endOffcanvas = $(this).find(".oj-offcanvas-end").first();
oj.SwipeToRevealUtils.tearDownSwipeActions(startOffcanvas);
oj.SwipeToRevealUtils.tearDownSwipeActions(endOffcanvas);
});
};
this.handleMenuBeforeOpen = function(event, ui)
{
var target = event.originalEvent.target;
var context = $("#listview").ojListView("getContextByNode", target);
if (context != null)
{
self.currentItem = $("#"+context['key']);
}
else
{
self.currentItem = null;
}
};
this.handleMenuItemSelect = function(event, ui)
{
var id = ui.item.prop("id");
if (id == "read")
self.handleRead();
else if (id == "more1" || id == "more2")
self.handleMore();
else if (id == "tag")
self.handleFlag();
else if (id == "delete")
self.handleTrash();
};
this.closeToolbar = function(which, item)
{
var toolbarId = "#"+which+"_toolbar_"+item.prop("id");
var drawer = {"displayMode": "push", "selector": toolbarId};
oj.OffcanvasUtils.close(drawer);
};
this.handleAction = function(which, action, event)
{
if (event != null)
{
self.currentItem = $(event.target).closest(".item-marker");
// offcanvas won't be open for default action case
if (action != "default")
self.closeToolbar(which, self.currentItem);
}
if (self.currentItem != null)
self.action("Handle "+action+" action on: "+self.currentItem.prop("id"));
};
this.handleRead = function(data, event)
{
self.handleAction("first", "read", event);
};
this.handleMore = function(data, event)
{
self.handleAction("second", "more", event);
};
this.handleFlag = function(data, event)
{
self.handleAction("second", "Rejected", event);
};
this.handleTrash = function(data, event)
{
self.handleAction("second", "Accepted", event);
self.remove(self.currentItem);
};
this.handleDefaultAction = function(item)
{
self.currentItem = item;
self.handleAction("second", "default");
self.remove(item);
};
this.remove = function(item)
{
// unregister swipe to reveal for removed item
var startOffcanvas = item.find(".oj-offcanvas-start").first();
var endOffcanvas = item.find(".oj-offcanvas-end").first();
oj.SwipeToRevealUtils.tearDownSwipeActions(startOffcanvas);
oj.SwipeToRevealUtils.tearDownSwipeActions(endOffcanvas);
alert(JSON.stringify(self.allItems()));
alert(item.toString());
self.allItems.remove(function(current)
{
return (current.id == item.prop("id"));
});
};
}
return PeopleViewModel;
});
HTML code:
<ul id="listview"
data-bind="ojComponent: {component: 'ojListView',
data: listViewDataSource,
item: {template: 'peoplelist_template'},
selectionMode: 'single',
ready: handleReady,
destroy: handleDestroy,
optionChange: changeHandler,
rootAttributes: {style: 'width:100%;height:100vh;overflow:auto; margin-top: 5px'},
scrollPolicy: 'loadMoreOnScroll',
scrollPolicyOptions: {fetchSize: 10}}">
</ul>
<script id="peoplelist_template">
<div style="padding:0.8571rem">
<div class="oj-flex oj-flex-items-pad">
<div class="oj-flex-item oj-lg-4 oj-md-4">
<img alt="employee image" class="demo-circular demo-employee-photo" style="float:left;" data-bind="attr: {src: $parent.getPhoto($data['name'])}"/>
<h2 class="demo-employee-name" data-bind="text: $data['from']"></h2>
<div class="demo-employee-title" data-bind="text: $data['title']"></div>
<div class="demo-employee-dept" data-bind="text: $data['deptName']"></div>
</div>
<div style="line-height: 1.5em; height: 3em; overflow: hidden; text-overflow: ellipsis" class="oj-text-sm oj-text-secondary-color" data-bind="text: $data['content']"></div>
</div>
</div>
<div tabIndex="-1" data-bind="attr: {id: 'first_toolbar_'+empId}" class="oj-offcanvas-start" style="width:75px">
<div data-bind="click:$parent.handleRead">
<div class="oj-flex-bar" style="height:100%">
<div class="oj-flex-bar-center-absolute">
<div class="oj-flex oj-sm-flex-direction-column">
<div title=".demo-library-icon-24" role="img" class="oj-flex-item demo-library-icon-24 demo-icon-font-24"></div>
<div style="padding-top: 10px" class="oj-flex-item">Read</div>
</div>
</div>
</div>
</div>
</div>
<div tabIndex="-1" data-bind="attr: {id: 'second_toolbar_'+empId}" class="oj-offcanvas-end" style="width:225px">
<div class="oj-swipetoreveal-more" data-bind="click: $parent.handleMore">
<div class="oj-flex-bar" style="height:100%">
<div class="oj-flex-bar-center-absolute">
<div class="oj-flex oj-sm-flex-direction-column">
<div title=".demo-library-icon-24" role="img" class="oj-flex-item fa fa-bars"></div>
<div style="padding-top: 10px" class="oj-flex-item">More</div>
</div>
</div>
</div>
</div>
<div style="background-color:#b81900" data-bind="click: $parent.handleFlag" class="oj-swipetoreveal-flag">
<div class="oj-flex-bar" style="height:100%">
<div class="oj-flex-bar-center-absolute">
<div class="oj-flex oj-sm-flex-direction-column">
<div title=".demo-library-icon-24" role="img" class="oj-flex-item fa fa-times"></div>
<div style="padding-top: 10px" class="oj-flex-item">Reject</div>
</div>
</div>
</div>
</div>
<div style="background-color:#009638" data-bind="click: $parent.handleTrash" class="oj-swipetoreveal-alert oj-swipetoreveal-default">
<div class="oj-flex-bar" style="height:100%">
<div class="oj-flex-bar-center-absolute">
<div class="oj-flex oj-sm-flex-direction-column">
<div title=".demo-library-icon-24" role="img" class="oj-flex-item fa fa-check"></div>
<div style="padding-top: 10px" class="oj-flex-item">Approve</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</li>
</script>
Actual problem is the listItem is not getting removed while approving.(The Approve div is call Handletrash function).
I dont know where I went wrong ??could anyone help me to solve this issue??
There's a lot of code here, which makes it hard to understand what everything is intended to do, and harder to pinpoint what the problem might be. That's why it's best to make a Minimal, Complete, and Verifiable Example. Also, in the process of removing all the code that does not directly affect your problem, you may solve it yourself.
I notice in your code that you have a number of jQuery calls. That's a significant red flag. Your contract with Knockout is that you will manipulate your data model and Knockout will use it to control the DOM. If you "go behind Knockout's back" and manipulate the DOM yourself, you and Knockout are going to be stepping on each other's toes.
Knockout provides two ways for you to customize how it manipulates the DOM: animated transitions and custom bindings. "Swipe to reveal" sounds like a transition to me, but looking at your code, it appears there's a whole lifecycle involved, so I think you need to make a custom binding handler.
All of your DOM-manipulating code should be inside the binding handler, and all of it should be restricted to the element of the binding handler. There should be no document-wide selectors.

for loop runs only once in angularjs

In Js file:
$scope.isCheckboxChecked = function() {
var chks = document.getElementsByName('chk[]');
for (var i = 0; i < chks.length; i++)
{
if (chks[i].checked)
{
$scope.checkBoxClicked = true;
$('#btnUpdateData').attr("data-target", "#update-modal");
$('#btnUpdateData').attr("data-toggle", "modal");
break;
}
if ($scope.checkBoxClicked == false)
{
alert("Please select at least one checkbox");
}
}
}
In HTML
<div class="row" style="">
<button type="button" id="btnUpdateData" class="btn btn-info" ng-click="isCheckboxChecked()">Update</button>
</div>
This code checks if the checkbox is checked only once.
once the checkbox is unchecked, I want the for loop to run again.
Here's a Plunkr example of how you could watch a checkbox's statechange and do something when it changes:
https://plnkr.co/edit/kyEv7IyAXGFRdZjaD4vM?p=preview
var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope) {
$scope.$watch("testCheckBox", function(newVal, oldVal){
alert('Checkbox changed!')
});
});
Html:
<body ng-controller="MainCtrl">
<p>Check box test</p>
<input type="checkbox" name="testCheckbox" ng-model="testCheckBox"></input>
</body>

ng-if condition always fails

I'm using AngularJS
<div ng-repeat="l in kites">
<a ng-click="findit(l.green.num)">color</a>
<span ng-if="c_{{l.green.num}} == 'y'>kites is </span>
</div>
In my controller I have
$scope.cnt=[];
$scope.findit = function(c){
$scope.cnt.push(c);
angular.forEach($scope.cnt, function(value, key){
$scope['c_'+value] = 'y' ;
})
}
My problem is, I'm not getting the span value even the conditions falls true..
means while l.green.num is 5 , c_5 ='y'. But it is not accepted in the if condition. Please help me.
Below is your solution:
var $scope;
var app = angular.module('miniapp', []);
function Ctrl($scope) {
$scope.kites = [{
'green':{
'num':1
}
}]
$scope.cnt = [];
$scope.findit = function(c) {
$scope.cnt.push(c);
angular.forEach($scope.cnt, function(value, key) {
$scope['c_' + value] = 'y';
})
}
};
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="miniapp" ng-controller="Ctrl">
<div ng-repeat="l in kites">
<a ng-click="findit(l.green.num)">color</a>
<span ng-show="{{'c_'+l.green.num}} == 'y'">kites is </span>
</div>
</div>
I'm not sure you can use brackets in ng-if conditions. This won't interpolate the value before evaluation.
What you could do is adding a "selected" value to your kite when clicked.
Example :
Controller
$scope.findit = function(c){
c.selected = true;
}
View
<div ng-repeat="l in kites">
<a ng-click="findit(l.green)">color</a>
<span ng-if="l.green.selected">kites is </span>
</div>

Enable / Disable text on click on image button in Angularjs

I have a header text and a pencil image:
Here is the code snippet:
'use strict';
angular.module('myModule')
.directive('heading', function (messageFormatterUtil, templateHelperService,cartService) {
return {
restrict: 'E',
link: function(scope, elem, attrs)
scope.lineId = cartService.allLines[scope.$parent.$index].id;
scope.headingLineContent = templateHelperService.getComponentData(attrs.data).heading;
var title=scope.headingLineContent.title;
scope.headingLineContent = messageFormatterUtil.formatMessage
(title,[scope.$parent.$index + 1]);
scope.$watch('$parent.$index', function() {
scope.lineId = cartService.allLines[scope.$parent.$index].id;
scope.headingLineContent = messageFormatterUtil.formatMessage
(title,[scope.$parent.$index + 1]);
}, true);
scope.view = {
editableValue: scope.headingLineContent,
editorEnabled: false
};
scope.visible = true;
scope.toggle = function() {
scope.visible = scope.visible ? true : false;
};
scope.Open=function () {
scope.view.editorEnabled = true;
scope.view.editableValue = scope.headingLineContent;
var myEl = angular.element( document.querySelector( '#line'+scope.lineId ) );
myEl.attr('title',"true");
};
scope.disableEditor = function () {
scope.view.editorEnabled = false;
};
scope.save = function () {
scope.headingLineContent = scope.view.editableValue;
};
},
templateUrl: './app-modules/cart/views/heading.html'
};
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<span ng-hide="visible" ng-show="show" ng-mouseout="!show" class="m-t-lg m-b-sm inline-block ng-binding">
<input type="text" id="from" />
</span>
<h3 class="m-t-lg m-b-sm inline-block " id="line{{lineId}}" ng-show="!show">{{headingLineContent}}</h3>
<i class="fa fa-pencil pencil m-l-sm" ng-click="open()" ng-mousedown="save()"></i>
Q1. How to enable the header text(as text field) when clicking on the pencil image ?
Q2. When click mouse out of the text field it should convert to header text again and the edited value should save in the the session.
You need to add a state of your header text
$scope.editable = false;
Then create an input with ng-show="editable" and ng-model="headingLineContent", then add ng-show="!editable" to your header.
add ng-click callback for a pencil image, and change the editable there. If your need to make a request to save the data, you can also do it there.
You can apply this logic:
In HTML:
<pencil-icon data-ng-click="editHeader()"></pencil-icon>
header text: <input type="text" ng-mouseleave="save()" data-ng-show="editEnable" ng-model="headerText"/>
<span data-ng-show="!editEnable">{{headerText}}</span>
In controller: (Make sure you inject $sessionStorage in your controller)
$scope.headerText = "Sample header text";
$scope.editEnable = false;
$scope.editHeader = function(){
$scope.editEnable = !$scope.editEnable
};
$scope.save = function(){
$sessionStorage.headerText = $scope.headerText;
$scope.editEnable = false;
}

What does this tag do?

I have been learning how to read other people's code and when ever I see something like this <meganav-item item="item" ng-repeat="item in website.nav.primary"></meganav-item> I get stuck.
I have a basic understand of angular, but the problem is the <meganav> tag. I do not know what this is..I have done a Google search, but nothing useful is showing.
Update
I have managed to locate the file of the <meganav> element. After following the instructions from the links that you guys have provided, it led me to a file named "MegaNavItem.js". Here is the code:
window.tcoStore.directive('meganavItem', ['$timeout','transport', function($timeout,transport) {
var lockTimeout = false;
var meganavLocks = transport.getModel('meganavLocks', {lock : false});
var clear = function (){
if(meganavLocks.timeout){
$timeout.cancel(meganavLocks.timeout);
}
}
var action = function(callback, time) {
if(meganavLocks.lock){
return;
}
clear();
meganavLocks.timeout = $timeout(callback, time);
}
var dropLock = function(callback, time) {
meganavLocks.lock = false;
}
return {
restrict : 'E',
replace: true,
templateUrl : '/page/header/meganav/item.html',
scope : {
item : '=',
clickOnly : '#',
delayIn : '#',
delayOut : '#'
},
link : function($scope, elem, attrs){
if(!$scope.clickOnly){
$scope.delayInValue = parseInt($scope.delayIn || 300,10);
$scope.delayOutValue = parseInt($scope.delayOut || 500,10);
elem.on('mouseenter', $scope.showDelayed);
if($scope.delayOutValue > 0){
elem.on('mouseleave', $scope.hideDelayed);
}
}
},
controller: ['$scope', '$timeout', 'transport', '$location' ,
function($scope, $timeout, transport,$location) {
// When $location changes ...
$scope.$on('$locationChangeSuccess', function() {
$scope.hide(true);
$scope.isActive = !_.isUndefined($scope.item.link) && ($scope.item.link.replace(/\/+$/,'') == $location.path().replace(/\/+$/,''));
});
$scope.loadSubmenu =0;
// tranposrt model accessable by other items
var meganavVisibleModel = transport.getModel('meganavActive');
var meganavVisibleModelId = $scope.item.$$hashKey;
meganavVisibleModel[meganavVisibleModelId] = false;
// hide and show funs
$scope.hide = function(forceFullClose){
clear();
meganavVisibleModel[meganavVisibleModelId] = false;
if(forceFullClose) {
meganavLocks.lock = true;
$timeout.cancel(lockTimeout);
lockTimeout = $timeout(dropLock, 1000);
}
};
$scope.hideDelayed = function (delay) {
action($scope.hide, _.isNumber(delay) ? delay : $scope.delayOutValue);
};
$scope.show = function(){
if(meganavLocks.lock){
return;
}
clear();
$scope.loadSubmenu = 1;
for(var i in meganavVisibleModel){
meganavVisibleModel[i] = (meganavVisibleModelId == i);
}
};
$scope.showDelayed = function (delay) {
action($scope.show, _.isNumber(delay) ? delay : $scope.delayInValue);
};
$scope.$watch(function(){
$scope.visible = meganavVisibleModel[meganavVisibleModelId];
});
// first touch click, second touch go to link
$scope.touch = function($event, path){
if(!$scope.visible) {
//$event.preventDefault();
$scope.show();
}else if(tco.empty(path)) {
$scope.hide();
} else {
if(path.match(/^https?:/)){
window.location.href = path;
}else{
$location.path(path);
}
}
}
}]
}
}]);
And this file led me to another file named item.html. The code :
<li class="header--menu__item my-repeat-animation" ng-class="{ 'is-active': isActive, open : visible && item.groups.length}" off-click="hide()" >
<a ng-if=":: item.groups.length"
ng-class="{active: item.active}"
class="header--menu__item--link has-children"
ng-click="show()"
title="{{::item.name}}">
{{::item.name}}
</a>
<a ng-if=":: !item.groups.length"
class="header--menu__item--link"
href="{{::item.link}}"
title="{{::item.name}}">
{{::item.name}}
</a>
<div class="header-menu-dropdown ng-hide" ng-show="visible" ng-if=":: item.groups.length">
<ul class="header-menu-dropdown__meganavGroup">
<li ng-repeat="meganavGroup in item.groups" class="header--menu-group">
<span class="meganav--group--name">{{::meganavGroup.name}}</span>
<ul class="meganav--group--items">
<li ng-repeat="groupItem in meganavGroup.items">
{{::groupItem.name}}
<span class="icon"></span>
</li>
</ul>
</li>
<li class="header-menu-offers" ng-repeat="offer in item.offers">
<a href="{{::offer.offer_link}}" class="placeholder">
<img tco-image="offer.offer_image" crop="3" alt="{{::offer.offer_name}}" />
</a>
<span class="offer-name">{{::offer.offer_name}}</span>
</li>
</ul>
<div class="header-menu-message" ng-bind-html="item.message"></div>
</div>
</li>
My issue is now that I cannot make out what where to find {{::item.name}}, which is the thing that I want to change. What technique can I use to find {{::item.name}}?
Sorry for all the noob questions! Your help is much appreciated!
In Angular it is possible to build your own HTML element. You won't find any information about this element because it doesn't exist. The developer has created that on its own and handles the content inside a module. Have a look at http://www.aleaiactaest.ch/2012/07/29/build-your-own-html-element-with-angular/ for more information.
Hope this helps, Cheers.
As i've noticed it's Angular App, so probably there are defined an directive which is called meganavItem. See Angular Directive for more information, you have to find definition of that directive and discover what is html layout and logic lives under <meganav-item>. However if there are no directive with defined name.
Also it may be separate registered element, see "Custom Elements
"article of how it's done and it would be more easy for you to find out how it works ( if it registered in that way...)