angular material design md-switch doesnt work within a tab - angularjs

when placing a switch ( md-switch directive) within a tab, an aria error is thrown
ARIA: Attribute " aria-label ", required for accessibility, is missing on node: ​…​​
this happens regardless on whether an aria label is present or not. If the switch is moved outside of the tab, it works as expected.
plunker showing the issue
http://plnkr.co/edit/FmZAyLBpzhURbdZuuhQK?p=preview
<div ng-app="app" ng-controller="ctrl" >
<md-tabs md-selected="selectedIndex">
<md-tab id="tab1">Item One</md-tab>
</md-tabs>
<ng-switch on="selectedIndex" class="tabpanel-container">
<div role="tabpanel" id="tab1-content" ng-switch-when="0">
<div>
<md-switch aria-label="toggle" ng-model="data.switch">Switch : {{ toggle }}</md-switch>
</div>
</div>
</ng-switch>
</div>
<script>
var app = angular.module('app', ['ngMaterial']);
app.controller("ctrl", function ($scope) {
$scope.toggle = false;
$scope.selectedIndex = 0;
});
</script>

That was strange..
This issue seems to be fixed with the most current build of angular material (version 0.6.1-master-0767813).
Here's the plunker: http://plnkr.co/edit/chEaf9i50mIiThp0Jloq?p=preview
I just changed the scripts to the most current build:
<link rel="stylesheet" href="//rawgit.com/angular/bower-material/master/angular-material.css">
<script src="//rawgit.com/angular/bower-material/master/angular-material.min.js"></script>
Also you needed to change the ng-model to the toggle value. So instead of using
ng-model="data.switch"
You needed to use
ng-model="toggle"
pointing to $scope.toggle.

Related

Duplicated Paypal buttons with Paypal REST API and AngularJS

I'm building an Single Page App where the paypal button is generated on ng-click from a button (Add products).
The problem I'm facing, is that if the user clicks this button several times, the app will generate several buttons one after the other.
This can very well happen as the user might click the button, but then go back and add an extra product, before finish the purchase.
How could I manage to remove all existing buttons before adding the new one?
The function looks like this:
$scope.formulari = function(){
paypal.Button.render({
env: 'production', // Or 'sandbox'
locale: 'es_ES',
style: {
label: 'paypal',
...
And after a few clicks, my initial HTML button <a id="paypal-button"></a> looks like this:
<a id="paypal-button">
<div id="xcomponent-paypal-button-6d3dcbc0c4" class="paypal-button paypal-button-context-iframe paypal-button-label-paypal paypal-button-size-large paypal-button-layout-horizontal" style=""></div>
<div id="xcomponent-paypal-button-46823018c3" class="paypal-button paypal-button-context-iframe paypal-button-label-paypal paypal-button-size-large paypal-button-layout-horizontal" style=""></div>
<div id="xcomponent-paypal-button-41aad29e14" class="paypal-button paypal-button-context-iframe paypal-button-label-paypal paypal-button-size-large paypal-button-layout-horizontal" style=""></div>
<div id="xcomponent-paypal-button-48d3247535" class="paypal-button paypal-button-context-iframe paypal-button-label-paypal paypal-button-size-large paypal-button-layout-horizontal" style=""></div>
</a>
Generating a button on click might not be the way you want to go with an AngularJs structure. Editing your DOM structure is more a jQuery thing and in general you don't want to mix the two (Some explanations of why: 1, 2).
An Angular way to pick this up would be the following (Explanation beneath snippet):
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope) {
$scope.articles = ['PC', 'Playstation', 'Xbox'];
$scope.cart = [];
$scope.addArticleToCart = function(article) {
$scope.cart.push(article);
}
$scope.clearCart = function() {
$scope.cart = [];
}
$scope.doPaypalThings = function() {
//REST API stuff
}
});
<!DOCTYPE html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.min.js"></script>
</head>
<body>
<div ng-app="myApp" ng-controller="myCtrl">
<div ng-repeat="article in articles">
<button ng-click="addArticleToCart(article)">
{{article}}
</button>
</div>
<br>
<div ng-show="cart.length > 0">
<button id="paypal-button" ng-click="doPaypalThings()">
Paypal
</button>
</div>
<br>
<div>
In cart:
</div>
<div ng-repeat="item in cart">
{{item}}
</div>
<br>
<div>
<button ng-click="clearCart()">
Clear cart
</button>
</div>
</div>
</body>
</html>
With this method the button always exists, it just isn't visible until the requirements within the ng-show are met. In the example, the requirement is that there are items in the cart. You will notice that once the requirements are no longer met the button will disappear again.
An opposite of ng-show is ng-hide which can be used in the same way:
ng-hide="cart.length == 0" or ng-hide="cart.length < 1
If you're dead set on using your current method, you can check out this answer here, although it is not Angular.

How to get value from <div> tag when input change in angular js?

I'm using WMD library to create an editor. When I input data into text area, my preview change data such as preview content from the input.
My question: Can I get content from the content of div preview? .How to do that?
<textarea id="wmd-input" ng-model="params.content" class="wmd-panel"></textarea>
<div id="wmd-preview" class="wmd-preview" ></div>
You can do this using angular.element delegates to Angular's built-in subset of jQuery,
$scope.content= angular.element(document.querySelector('#wmd-preview'));
alert($scope.content);
You can output your textarea value with $scope using ng-bind-html-unsafe inside your code HTML element. It does work like in this -> Fiddle:
View
<div ng-controller="MyCtrl">
<textarea id="wmd-input" ng-model="params.content" class="wmd-panel"></textarea>
<div id="wmd-preview" class="wmd-preview">
<pre>
<code ng-bind="params.content"></code>
</pre>
</div>
</div>
App & Controller
var myApp = angular.module('myApp',[]);
function MyCtrl($scope) {
$scope.params = {
content: "<h1>Hello World</h1>"
}
}
Output
> <html>
> <head></head>
> <body>
> <h1>Hello World</h1>
> <body>
> </html>

Bootstrap 3: Deselect tab using angular js

I'm working with angular js and bootstrap 3 and my app works like ... I have a view where you have several links which let you show a div with several tabs and select one of them. This works fine. But if I change the tab through a click over it and then I hide the view with the tabs when I make click on another click I show the view with the tabs, with the tab selected from the link, that's correct, but ... with the previous tab clicked.
So, how I can deselect the tab where I have been make click over it?
Edit 1:
I'm going to post several screenshots to try to explain better my problem.
Edit 2:
I add this plunker to show how it works my code and you can check that if you clic on a tab, if later returns clicking a button you don't select the correct tab. https://plnkr.co/edit/y22T01OwxgttDWM1mJeH
HTML:
<body ng-controller="MainCtrl as ctrl">
<button id="bTab1" ng-click="ctrl.buttonClicked($event)">
Tab 1
</button>
<button id="bTab2" ng-click="ctrl.buttonClicked($event)">
Tab 2
</button>
<button id="bTab3" ng-click="ctrl.buttonClicked($event)">
Tab 3
</button>
<div ng-show = "ctrl.show_tabs">
<div class = "row" style = "text-align: right; margin-top: 10px">
<button ng-click="ctrl.closeTab()">
Hide Tabs
</button>
</div>
<ul class="nav nav-tabs" id="myTab">
<li ng-class = "ctrl.active_pai"><a data-target="#pai" data-toggle="tab">PAI</a></li>
<li ng-class = "ctrl.active_pap"><a data-target="#pap" data-toggle="tab">PAP</a></li>
<li ng-class = "ctrl.active_ip"><a data-target="#ip" data-toggle="tab">IP</a></li>
</ul>
<div class="tab-content">
<div class="tab-pane" ng-class = "ctrl.active_pai" id="pai">Content PAI</div>
<div class="tab-pane" ng-class = "ctrl.active_pap" id="pap">Content PAP</div>
<div class="tab-pane" ng-class = "ctrl.active_ip" id="ip">Content IP</div>
</div>
</div>
</body>
Javascript:
var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope) {
var self = this;
$scope.name = 'World';
self.show_tabs = false;
self.active_pai = "";
self.active_pap = "";
self.active_ip = "";
self.buttonClicked = function(event) {
self.show_tabs = true;
if (event.currentTarget.id == "bTab1"){
self.active_pai = "active";
self.active_pap = "";
self.active_ip = "";
}
if (event.currentTarget.id == "bTab2"){
self.active_pai = "";
self.active_pap = "active";
self.active_ip = "";
}
if (event.currentTarget.id == "bTab3"){
self.active_pai = "";
self.active_pap = "";
self.active_ip = "active";
}
};
self.closeTab = function(){
self.show_tabs = false;
}
});
Edit 3:
More problems:
In my code, I've got tabs and Bootstrap calendar and with the given solution works fine without bootstrap calendar, but If add bootstrap calendar, this doesn't work correctly.
I have modified my origina plunker and I have added a bootstrap calendar and change these libraries:
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-bootstrap/1.3.2/ui-bootstrap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-bootstrap/1.3.2/ui-bootstrap-tpls.min.js"></script>
By these:
<script type="text/javascript" src="bootstrap.min.js"></script>
<script type="text/javascript" src="ui-bootstrap-tpls-0.14.3.min.js"></script>
The code of these libraries you've got on the plunker. Plus I have added the controller which manage the bootstrap calendar.
Ok, If we go to the plunker: https://plnkr.co/edit/PaSqa0jxQjz48pzcmBMa
We can see that we have a bootstrap calendar where I cannot select day greater than today + 1. That's correct! But, If I make a click on button "Tab 2", the Tab that we can see is not 2, it's 1. If I do the same with tab 3, I've got the same result. That's wrong. The correct functionality is If I make a click on button "Tab 2", we can see tab 2, for example.
Ok, If I change on the plunker these libraries ...
<script type="text/javascript" src="bootstrap.min.js"></script>
<script type="text/javascript" src="ui-bootstrap-tpls-0.14.3.min.js"></script>
By the given in the solution:
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-bootstrap/1.3.2/ui-bootstrap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-bootstrap/1.3.2/ui-bootstrap-tpls.min.js"></script>
We can see that the tabs works correctly, but bootstrap calendar lets you to select days greater than today + 1. And this is wrong!
I would recommend using angular-ui-bootstrap tabs for this. It provides angular wrappers around most of the bootstrap functionality (mostly directives), so it makes these types of things much easier to write (and code is cleaner, as you'll see below). I modified your plunkr as minimally as possible, but changed it to make use of the ui-bootstrap tabs: https://plnkr.co/edit/qqvY2acsZWbkyFCCT7qr?p=info
New Controller:
app.controller('MainCtrl', function($scope) {
var self = this;
$scope.name = 'World';
self.buttonClicked = function(index) {
self.show_tabs = true;
self.active = index;
};
self.closeTab = function(){
self.show_tabs = false;
}
});
Html changes:
<button id="bTab1" ng-click="ctrl.buttonClicked(1)">
Tab 1
</button>
<button id="bTab2" ng-click="ctrl.buttonClicked(2)">
Tab 2
</button>
<button id="bTab3" ng-click="ctrl.buttonClicked(3)">
Tab 3
</button>
...
<div ng-show = "ctrl.show_tabs">
...
<uib-tabset active="ctrl.active">
<uib-tab index="1" heading="PAI">Content PAI</uib-tab>
<uib-tab index="2" heading="PAP">Content PAP</uib-tab>
<uib-tab index="3" heading="IP">Content IP</uib-tab>
</uib-tabset>
</div>
ctrl.active, which is passed into the active attribute on <uib-tabset> just represents the index of the currently opened tab, so just changing its value will change which tab is open/visible. There are some more attributes that can be used for these directives (you can see them on the page I linked to above), but this shows the basis of how these tab directives can be used. I haven't seen the issue you were describing above after these changes.

angularjs sanitize not work properly with ng-model

I use AntiXss Encoder on serverside for XSS atacks so all response includes html unescape characters like "&lt:script&gt:alert(1);&lt:/script&gt:" (replaced ';' as ':')
on binding i use sanitize with ng-bind-html there is no problem wih that.
There is an other control input for update mode. When user needs to update text they click update icon then i show textarea and hide binded tag with ng-if. textarea has ng-model attr. i cant escape html characters on textarea like ng-bind-html here is the snippet pls help im getting creazy..
in fiddle; edit mode textarea must display "<script>alert(1);</script>" with no alert action and data will be sent to the server must display same too...
here is the fiddle
var app = angular.module('myApp',['ngSanitize']);
app.controller('MyCtrl', function($scope, $sce, $sanitize) {
$scope.post1 = "<script>alert(1);</script>";
//$scope.post2 = $sce.parseAsHtml("<h1>alert(1)</h1>");
$scope.logs = ["log created"];
$scope.log = function(val){
$scope.logs.push(val);
}
});
.label {
text-decoration:underline;
color:red;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular-sanitize.min.js"></script>
<div ng-app="myApp">
<div ng-controller="MyCtrl">
<div class="label">Edit mode :</div>
<textarea ng-model="post1" style="width:100%;" rows="5"></textarea><br />
<div class="label">Binding mode :</div>
<div ng-bind-html="post1"></div><br />
<div class="label">Data will be send to the server :</div>
<div>{{post1}}</div><br />
<div class="label">Logs (if needed) :</div>
<div ng-repeat="d in logs">
<p>{{($index+1) + ". " + d}}</p>
</div>
</div>
</div>

AngularJS ng-show 2 way binding not working

I am new to AngularJS and I have seen others asking similar questions, but the answers are not working for me. Rather than hijacking those questions, I thought I would open one for myself.
I am creating a demo app -- it lists "sites" which can be added to or deleted. I am using the ng-show attribute to display the required html div while hiding the others.
Here is the back-end javascript--
var SiteMaintenanceModule = angular.module("SitesMaintenance", []);
SiteMaintenanceModule.controller("siteCtrl", diveSiteCtrlfn);
function diveSiteCtrlfn($scope) {
// initializing the sites array
$scope.sites = sites;
//initializing the Divs array
$scope.allowedDivs = ["listSiteDiv","addSiteDiv", "editSiteDiv","deleteSiteDiv"];
// setting the first div as selected. This should show the div which lists the sites
$scope.selectedDiv = $scope.allowedDivs[0];
// function to be called with the selected div is to be changed
$scope.setSelectedDiv = function ($divSelectedByUser) {
$scope.selectedDiv = $divSelectedByUser;
}
};
And here is the html
<html xmlns="http://www.w3.org/1999/xhtml" ng-app="SitesMaintenance">
<head>
<title>List of Dive Sites</title>
<link rel="Stylesheet" href="./../zHelpers/bootstrap/css/bootstrap.css" />
<script src="./../zHelpers/angular.min.js"></script>
<script src="./sites.js"></script>
<script src="./SiteMaintenance.js"></script>
</head>
<body ng-controller="siteCtrl">
<!-- Display the list of sites based on the selectedDiv variable-->
<div id="SiteList" ng-show="{{selectedDiv == 'listSiteDiv'}}">
<h3>List of Sites</h3>
<ul ng-repeat="site in sites" ng-model="sites">
<li>{{site.site}} in {{site.location}}</li>
</ul>
</div>
<!-- Display the add site Div based on the selectedDiv variable-->
<div id="AddSite" ng-show="{{selectedDiv == 'addSiteDiv'}}">
<h3>Add New Site</h3>
<div style="display:block; margin:10px">Site: <input id="inputAddSiteName" /></div>
<div style="display:block; margin:10px">Location: <input id="inputAddSiteLocation" /></div>
</div>
<!-- Display the edit site Div based on the selectedDiv variable -->
<div id="EditSites" ng-show="{{selectedDiv == 'editSiteDiv'}}" style="display:block;margin:20px">
Site Name:<input id="InputEditSiteName" />
Site Location:<input id="InputEditSiteLocation" />
</div>
<div id="controls">
<button id="AddNewSiteButton" ng-click="setSelectedDiv('addSiteDiv')">Add Site</button>
<button id="DeleteSiteButton" ng-click="setSelectedDiv('deleteSiteDiv')">Delete Site</button>
<button id="EditSiteButton" ng-click="setSelectedDiv('editSiteDiv')">Edit Site</button>
</div>
</body>
I can set the visible div to whatever I want at the start, by changing the index in the statement "$scope.selectedDiv = $scope.allowedDivs[0];" in the JavaScript.
I change the value of $scope.selectedDiv when any of the buttons on the page are clicked, so as to change the visibility of the divs.
However, the visibility of the divs doesn't change, no matter what the value of $scope.selectedDiv is. In fact, when debugging in chrome, I see that the attribute value of ng-show for each of my divs updates dynamically to "true" or "false" and expected, but the div is still displayed -- the initially invisible divs seems to have a class="ng-hide" attribute, which never changes.
I have tried $scope.$apply() in the JavaScript but that gives errors. Any help would be greatly appreciated.
You don't need to use {{}} interpolation inside ng-show directive directive, it evaluates the expression inside a $scope of your controller directly.
ng-show="selectedDiv == 'addSiteDiv'"
ng-show="selectedDiv == 'listSiteDiv'"
ng-show="selectedDiv == 'editSiteDiv'"

Resources