AngularJS: display a block of html after button click - angularjs

I am trying to write a controller to handle the button click of the "New" button. The goal is for the lower block of code (starting <div ng-show="buttonClick">) to be initially hidden. When "New" button is clicked I would like the lower block of code to appear.
The problem I'm having is that the lower block of code is visible when I load the page. It is never hidden.
{% extends "base.html" %}
{% block content %}
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
<div class="container-fluid">
<div class="row">
<div class="col-sm-10 col-sm-offset-1">
<h2>Ratings</h2>
<table class="table table-bordered">
<thead>
<tr>
<th>Beer Name</th>
<th>Beer Rating</th>
<th>Notes</th>
<th>Brewer</th>
</tr>
</thead>
<tbody>
{% for rating in ratings %}
<tr>
<td>{{ rating.beer_name }}</td>
<td>{{ rating.score }}</td>
<td>{{ rating.notes }}</td>
<td>{{ rating.brewer }}</td>
<td>Edit</td>
<td><a class="btn btn-primary" href="{% url 'rating-delete' rating.id %}" value="{{ rating.id }}" name="delete" >Delete</a></td>
</tr>
{% endfor %}
</tbody>
</table>
<div ng-app="myApp" ng-controller="myCtrl">
<a ng-model="buttonClick" ng-click="is_clicked()" class="btn btn-primary">New</a>
</div>
</div>
</div>
<div ng-show="buttonClick" >
<div class="container-fluid">
<div class="row">
<div class="col-sm-10 col-sm-offset-1">
<h2>Enter a new rating</h2>
<form role="form" method="post">
{% csrf_token %}
<p>Beer Name: {{ form.beer_name }}</p>
<p>Score: {{ form.score }}</p>
<p>Notes: {{ form.notes }}</p>
<p>Brewer: {{ form.brewer }}</p>
<p><button type="submit" class="btn btn-primary">Submit</button></p>
</form>
</div>
</div>
</div>
</div>
</div>
<script>
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope){
$scope.buttonClick = false;
$scope.is_clicked = function() {
$scope.buttonClick=true;
console.log($scope.buttonClick)
}
})
</script>
{% endblock %}

On this line
app.controller('myCtrl', function($scope)) {
Remove the last )
When your code will work, you will probably have a "blink" effect with your block. It will appear at the loading of the page, then it will disappear when Angular will start. If you have the "blink" effect, you will need to add ng-cloack on the block.
<div ng-show="buttonClick" ng-cloak>

I'd probably try it like this (untested):
<div ng-app="myApp" ng-controller="myCtrl">
<div><a ng-click"buttonClick = !buttonClick" class="btn btn-primary">New</a></div>
<script>
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope)) {
$scope.buttonClick = false;
}
</script>

Related

AngularJS - ng-repeat of rows inside tables

AngularJS - ng-repeat & $http.get
Edit: Tried using unique, also did not work:
<table class="table" ng-controller="fetchData">
<tr ng-repeat="elements in rawData.value">
<th ng-repeat="(key, value) in elements | unique:'key'">
{{key}}
</th>
<td ng-repeat="element in elements">
{{ element }}
</td>
</tr>
</table>
I'm filling tables with external information using ng-repeat, but I am struggling with filling the headers. I found an example to extract the keys:
<td ng-repeat="(key, element) in elements">
However, this does not help me as I should fill the th just one time, over the data, not beside it. I also tried adding an additional ng-repeat, to no avail.
Regaring $http.get and ODATA-sources - is there any way to populate the table with all available data at once? Or anywhere I can read which tokens are accepted (did not find any information when googling)? Right now I'm only geting a max of 11 elements - and I'm not allowed to add the token to the URL the way I am doing at the moment. Is there a better way to fetch the data? Any pointers would be appreciated, please let me know if additional information is needed. This is the code:
<html>
<head>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
<script src="https://code.jquery.com/jquery-3.0.0.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.0/umd/popper.min.js" integrity="sha384-cs/chFZiN24E4KMATLdqdvsezGxaGsi4hLGOzlXwp5UZB1LY//20VyM2taTB4QvJ" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.0/js/bootstrap.min.js" integrity="sha384-uefMccjFJAIv6A+rW+L4AHf99KvxDjWSu1z9VI8SKNVmz4sk7buKt/6v9KI65qnm" crossorigin="anonymous"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.9/angular.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/ODataResources/1.0.25/odataresources.min.js"></script>
<link rel="stylesheet" href="/css/style.css">
</head>
<script>
const BASE_URL = 'http://services.odata.org/V3/OData/OData.svc/';
function getParameterByName(name, url) {
if (!url) url = window.location.href;
name = name.replace(/[\[\]]/g, "\\$&");
var regex = new RegExp("[?&]" + name + "(=([^&#]*)|&|#|$)"),
results = regex.exec(url);
if (!results) return null;
if (!results[2]) return '';
return decodeURIComponent(results[2].replace(/\+/g, " "));
}
var app = angular.module('getData', []);
app.controller('fetchLinks', function($scope, $http) {
$http.get(BASE_URL)
.then(function(response) {
$scope.rawLinks = response.data;
});
});
app.controller('fetchData', function($scope, $http) {
let dynamicContent = getParameterByName('q');
console.log(BASE_URL+dynamicContent);
$http.get(BASE_URL+dynamicContent)
.then(function(response) {
$scope.rawData = response.data;
});
});
</script>
<body ng-app="getData">
<div class="container main-container">
<div class="row">
<div class="col menu">
<nav class="navbar navbar-expand-lg navbar-light bg-light">
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarNav">
<ul>
<div ng-controller="fetchLinks">
<li class="nav-item" ng-repeat="element in rawLinks.value">
<a class="nav-link" href="?q={{ element.url }}">{{ element.name }}</a>
</li>
</div>
</ul>
</div>
</nav>
</div>
</div>
<div class="row">
<div class="col-md-12 content">
<table class="table" ng-controller="fetchData">
<tr ng-repeat="elements in rawData.value">
<td ng-repeat="element in elements">
{{ element }}
</td>
</tr>
</table>
</div>
</div>
</div>
</div>
</body>
</html>
To repeat multiple rows, use the Special Repeat Start and End Points:
<table class="table" ng-controller="fetchData">
<tr ng-repeat-start="elements in rawData.value">
<th ng-repeat="(key, value) in elements>
{{key}}
</th>
</tr>
<tr ng-repeat-end>
<td ng-repeat="element in elements">
{{ element }}
</td>
</tr>
</table>
This will repeat two rows; the first with keys and the second with values.
Your code does almost what I wanted to achieve, so I added an ng-if="$first" to the ng-repeat-start line
If your goal is to create only one header row, it is more efficient to do it as:
<table class="table" ng-controller="fetchData">
<tr>
<th ng-repeat="(key, value) in rawData.value[0]">
{{key}}
</th>
</tr>
<tr ng-repeat="elements in rawData.value">
<td ng-repeat="element in elements">
{{ element }}
</td>
</tr>
</table>
This avoids all the overhead with evaluating multiple ng-if expressions. It also assumes that every object in the rawData.value array has the same keys.

can not show angular apps data in django template

Please help me to solve this problem.This angular code works locally but can not work in django template.
I call this static files end of the body of base.html
<script src="{% static "js/angular.min.js" %}"></script>
<script src="{% static "js/restangular.min.js" %}"></script>
<script src="{% static "js/angular-ui-router.min.js" %}"></script>
This is contactlist.html
<div id="contactlist" ng-app="newApp">
<div class="container" ng-controller="angCtrl">
<h1 class="text-center">Search contact for {{myModel}}</h1>
<form>
<div class="input-group">
<input type="text" class="form-control" ng-model="myModel"
placeholder="Search Contact">
<div class="input-group-btn">
<button class="btn btn-default" type="submit">
<i class="fa fa-search"></i>
</button>
</div>
</div>
</form>
<div class="all">
<table class="table table-hover text-center">
<thead>
<tr>
<th class="text-center">Id</th>
<th class="text-center">Name</th>
<th class="text-center">Contact Number</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="contact in contactlist | filter:myModel |
orderBy: 'name'">
<td>{{contact.id}}</td>
<td>{{contact.name}}</td>
<td>{{contact.contact}}</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
This is app.js
var app = angular.module('newApp', []);
app.controller('angCtrl', function($scope) {
$scope.name = "";
});
app.controller('angCtrl', function($scope) {
$scope.contactlist = [
{id:'1',name:'raisul',contact:'+8801723844330'},
{id:'2',name:'Rafikul',contact:'+8801723564330'},
{id:'3',name:'Shariful',contact:'+8801726864330'},
{id:'4',name:'kamarul',contact:'+8801723764330'},
{id:'5',name:'Ashraful',contact:'+8801728864330'},
{id:'6',name:'Jamarul',contact:'+8801723964330'},
{id:'7',name:'Rahul',contact:'+8801723861330'},
{id:'8',name:'Rashidul',contact:'+8801725864330'},
]
});
It shows the table element but can not show any data

AngularJS and ModelForm: Submit button not working

The page is supposed to display the contents of the database in a table, with a "New" button to add a new entry to the db. When the user clicks the "New" button, a form appears below. It is a ModelForm for the user to input a new entry to the Model, and then submit via a "Submit" button below. This was working as expected, until I added in an AngularJS controller to handle the button click of "New". The problem is my "Submit" button does not work. I want it to submit the data to the ModelForm, but it appears to do nothing.
Here is my template:
{% extends "base.html" %}
{% block content %}
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
<div class="container-fluid">
<div class="row">
<div class="col-sm-10 col-sm-offset-1">
<h2>Ratings</h2>
<table class="table table-bordered">
<thead>
<tr>
<th>Beer Name</th>
<th>Beer Rating</th>
<th>Notes</th>
<th>Brewer</th>
</tr>
</thead>
<tbody>
{% for rating in ratings %}
<tr>
<td>{{ rating.beer_name }}</td>
<td>{{ rating.score }}</td>
<td>{{ rating.notes }}</td>
<td>{{ rating.brewer }}</td>
<td>Edit</td>
<td><a class="btn btn-primary" href="{% url 'rating-delete' rating.id %}" value="{{ rating.id }}" name="delete" >Delete</a></td>
</tr>
{% endfor %}
</tbody>
</table>
<div ng-app="myApp" ng-controller="myCtrl">
<a ng-model="buttonClick" ng-click="is_clicked()" class="btn btn-primary">New</a>
<div ng-show="buttonClick" ng-cloak>
<div class="container-fluid">
<div class="row">
<div class="col-sm-10 col-sm-offset-1">
<h2>Enter a new rating</h2>
<form role="form" method="post">
{% csrf_token %}
<p>Beer Name: <input type="text" ng-model="myForm.beer_name"></input></p>
<p>Score: <input type="number" step="0.1" ng-model="myForm.score"></input></p>
<p>Notes: <input type="text" ng-model="myForm.notes"></input></p>
<p>Brewer: <input type="text" ng-model="myForm.brewer"></input></p>
<p><button ng-click="submit_to_form(myForm)" type="submit" class="btn btn-primary">Submit</button></p>
</form>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<script>
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope, $http){
$scope.myForm = {beer_name:'beer_name', score:'score', notes:'notes', brewer:'brewer'};
$scope.buttonClick = false;
$scope.is_clicked = function() {
$scope.buttonClick=true;
console.log($scope.buttonClick)
}
$scope.submit_to_form = function(data) {
$http.post('rating-home', data);
}
})
</script>
{% endblock %}
And urls.py:
from django.conf.urls import url
from django.contrib import admin
from ratings.views import home, RatingCreate, delete, edit
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^$', RatingCreate.as_view(), name='rating-home'),
url(r'rating/add/$', RatingCreate.as_view(), name='rating-add'),
url(r'rating/delete/(?P<row_id>[0-9]+)/$', delete , name='rating-delete'),
url(r'rating/edit/(?P<row_id>[0-9]+)/$', edit , name='rating-edit'),
]
And views.py for the Submit button:
class RatingCreate(View):
""" Create a new Rating """
form_class = RatingForm
template_name = 'home.html'
def get(self, request):
form = self.form_class()
context = {'ratings': Rating.objects.all(), 'form': form}
#return render(request, 'home.html', context)
return render(request, self.template_name, context)
def post(self, request):
form = self.form_class(request.POST)
if form.is_valid():
_ = form.save()
return redirect('rating-home')
return render(request, self.template_name, {'form: form'})
You should handle submitting the form with angular
<form ng-submit="myFunc(myData)">
<input type="text" ng-model="myData.name">
<input type="text" ng-model="myData.phone">
<button type="submit">Submit</button>
</form>
OR
<form >
<input type="text" ng-model="myData.name">
<input type="text" ng-model="myData.phone">
<button ng-click="myFunc(myData)">Submit</button>
</form>
and your controller:
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope){
$scope.myData= {name:'' , phone:''};
$scope.myFunc = function(data) {
console.log(data);
// data(myData array) can be send with angular $http.post() method
// e.g. : $http.post('/myUrl/', data)
}
})
Update:
Here is a good tutorial for angular $http service!

Edit many same name isolated variables at a time in Angularjs

I have a table. Each cell can hold its value as a string or the edit in place template for that datatype.
I render one thing or the other based on the value of the variable "ttt" of that table cell. If ttt=true it renders the editing template if false it renders the value as string.
The way things are set up you can toggle between true and false of a specific cell each time you double-click on it.
I wish to have as well a button at top of the page that toggles all the "ttt" variables between true or false at the same time for all the table cells.
What is the best way to do this the way I have things set up.
Here is the template of the table:
<script type="text/ng-template" id="editabletable">
<div ng-controller="listeditorController" cg-busy="{promise:myPromise, message:' '}">
<div tasty-table bind-resource-callback="getResource" bind-init="init" bind-filters="filterBy">
<div class="table-responsive" style="width:100%;">
<table class="superResponsive" adapt-table style="width:{{theWidth}};margin:0 auto;">
<thead>
<!-- <thead tasty-thead bind-not-sort-by="notSortBy"></thead> -->
<tr>
<th style="max-width:{{columnWidth}}px;" ng-repeat="attobj in rows[0].class_attributes()">
{{ attobj.label }}
</th>
</tr>
<tr>
<td style="max-width:{{columnWidth}}px;" ng-repeat="attobj in header.columns track by $index">
<input ng-if="attobj.filterable" type="text" class="form-control input-sm" ng-model="filterBy[attobj.filterkey || attobj.key]" ng-model-options="{ debounce: 2000 }" />
</td>
</tr>
</thead>
<tbody>
<tr ng-repeat="dbo in rows">
<td style="max-width:{{columnWidth}}px;" ng-repeat="attobj in header.columns" ng-dblclick="ttt=!ttt">
<div>
<form name="theForm" novalidate>
<div ng-if="ttt" ng-init="attobj = attobj.attobj" ng-include src="getAttValuesEditorTemplate(dbo, attobj)">
</div>
</form>
<div ng-if="!ttt" ng-repeat="v in dbo.get4(attobj.key) track by $index">
<p ng-if="v.cid">{{ v.displayName() }}</p>
<p ng-if="!v.cid">{{ v }}</p>
</div>
</div>
</td>
</tr>
</tbody>
</table>
</div>
<div tasty-pagination bind-list-items-per-page="listItemsPerPage" bind-items-per-page="itemsPerPage" bind-template-url="'/templates/table/pagination.html'"></div>
</div>
</div>
</script>
Ok, the solution I came up with is fairly simple but SLOW.
I added a controller at the table level which defines a scope variable "editGird" defined on load as "false".
On click of the button "Edit gird" the scope variable "editGird" toggles between true and false.
If set to true the cell is rendered like:
<td ng-if="editGird==true" style="max-width:{{columnWidth}}px;" ng-repeat="attobj in header.columns">
<div>
<form name="theForm" novalidate>
<div ng-init="attobj = attobj.attobj" ng-include src="getAttValuesEditorTemplate(dbo, attobj)">
</div>
</form>
</div>
</td>
If editGird == false:
<td ng-if="editGird==false" style="max-width:{{columnWidth}}px;" ng-repeat="attobj in header.columns" ng-dblclick="ttt=!ttt">
<div>
<form name="theForm" novalidate>
<div ng-if="ttt" ng-init="attobj = attobj.attobj" ng-include src="getAttValuesEditorTemplate(dbo, attobj)">
</div>
</form>
<div ng-if="!ttt" ng-repeat="v in dbo.get4(attobj.key) track by $index">
<p ng-if="v.cid">{{ v.displayName() }}</p>
<p ng-if="!v.cid">{{ v }}</p>
</div>
</div>
</td>
Controller:
app.controller('editGirdController', ['$scope',
function ($scope) {
$scope.editGird= false;
$scope.onOff = function() {
if ($scope.editGird == true){
$scope.editGird = false;
$scope.editGirdColor ='#0887A7';
} else{
$scope.editGird = true;
$scope.editGirdColor ='lightGreen';
}
console.log($scope.editGird);
console.log($scope);
}
}
]);
But this is very very slow!!!
On tables which have 25-35 columns it takes 1 second for each 5 rows to render!!!
How can I make this more efficient???

AngularJS filter ng-repeat by index?

I have a table and buttons inside a loop, this picture shows the results of what I get depending on the search
html
<div class="col-sm-4" ng-repeat="x in names">
<div class="panel panel-primary" id= "{{ x.myIndex }}" >
<div class="panel-heading">
<h3 class="panel-title">{{ x.ID }} {{ x.Name }}
<button ng-click="showCommentsWithID(x.ID)" style="float: right;" class="btn btn-xs btn-primary glyphicon glyphicon-comment"> 42</button>
</h3>
</div>
<div class="panel-body">
<table width="" border="0" ng-repeat="c in comments" id= "{{ c.ID}}" ">
<tr>
<td width="30">{{ c.ID }}</td>
<td >{{ c.Comment}}</td>
</tr>
</table>
</div>
</div>
</div><!-- /.col-sm-4 -->
js
function ContactController($scope,$http) {
$scope.showCommentsWithID= function(myID) {
var page = "mySQL.php?func=getComments&id=" + myID;
$http.get(page).success(function(response) {$scope.comments = response;});
}
}
When I click on the comment Button I want to display the comments according to that ID.
This is working fine except that the comments are loaded to all tables and not only to the table with the right ID. In this example I clicked on ID 1 Coka Cola.
Where do I need to apply a filter the js or html? both? ...
![enter image description here][3]stack.imgur.com/gqyPR.jpg
You can simply bind your comments with your product's id in order to make it unique for each product.
What we need to do is to add product's id to $scope.comments as following:
function ContactController($scope,$http) {
$scope.comments = {}; // Init comments object.
$scope.showCommentsWithID= function(myID) {
var page = "mySQL.php?func=getComments&id=" + myID;
$http.get(page).success(function(response) {$scope.comments[myID] = response;});
}
}
Then, you can simply loop through it:
<table width="" border="0" ng-repeat="c in comments[x.ID]" id= "{{ c.ID}}" ">
<tr>
<td width="30">{{ c.ID }}</td>
<td >{{ c.Comment}}</td>
</tr>
</table>

Resources