Add a div element dynamically in ng-repeat angularjs - html

I am using angularjs.I am doing ng-repeat to display list of notify types and i am display in li tag.In this list three values are default.I have one Add button next to the list.If i click add button then i need to display another list with the three default values.Again add button shifts place to next.And if i click add button again then it displays another list with default values and add button shifts place and this process goes on.
Here is the first list i am displaying with default and other values
<div class="col-xs-12 col-sm-4 col-md-4" data-ng-
if="workboardstages.length">
<ul class="simpleDemo row">
<li data-ng-repeat="workboard in workboardstages">
{{workboard.stageName}}
</li>
</ul>
</div>
Here is the add button i am placing next to the list
<div class="col-xs-12 col-sm-4 col-md-4">
<button data-ng-click="addNew()">Add New Workboard</button>
</div>
Here is how i am trying to display another list after clicking add button but i am not sure how to do it.
<div class="col-xs-12 col-sm-4 col-md-4" data-ng-show="flag">
<ul class="simpleDemo row">
<li data-ng-repeat="workboard in workboardStagesWithDefault">
{{workboard.Name}}
</li>
</ul>
</div>
Here is the Controller.js
$scope.workboardStagesWithDefault = [
{
Name:"New"
},
{
Name:"Won"
},
{
Name:"Lost"
}
];
$scope.flag=false;
$scope.addNew = function(){
$scope.flag=true;
};
$scope.getAllWorkboardStages = function(){
AccountSettingService.getAllWorkboardStages().then(function(response){
$scope.workboardstages = response.data;
});
}
Here after clicking add button i am displaying another list with default values "New","Won" and "Lost" but if i click another time add value it is not adding list again.I want to add lists whenever i click add button.But now it is adding only once.Can anyone tell how to keep adding the div list when add is clicked?

Each time you want to add a list add it to a list containing lists, $scope.listOfLists = [];. You could then use NgRepeat with the listOfLists and dynamically add more list to the view.
Here's an example:
angular.module("app",[]).controller("myCtrl",function($scope){
$scope.listOfLists = [];
$scope.workboardstages = [
{
stageName:"stageName1"
},
{
stageName:"stageName2"
},
{
stageName:"stageName3"
}
];
$scope.workboardStagesWithDefault = [
{
Name:"New"
},
{
Name:"Won"
},
{
Name:"Lost"
}
];
$scope.addNew = function(){
var clonedList = angular.copy($scope.workboardStagesWithDefault);
$scope.listOfLists.push(clonedList);
};
$scope.removeMe = function(index){
$scope.listOfLists.splice(index,1);
};
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app" ng-controller="myCtrl">
<div class="col-xs-12 col-sm-4 col-md-4" data-ng-
if="workboardstages.length">
<ul class="simpleDemo row">
<li data-ng-repeat="workboard in workboardstages">
{{workboard.stageName}}
</li>
</ul>
</div>
<div class="col-xs-12 col-sm-4 col-md-4" data-ng-show="listOfLists.length > 0">
<div data-ng-repeat="list in listOfLists">
<ul class="simpleDemo row">
<li data-ng-repeat="workboard in list">
{{workboard.Name}}
</li>
</ul>
<button ng-click="removeMe($index)">remove {{$index}}</button>
</div>
</div>
<div class="col-xs-12 col-sm-4 col-md-4">
<button data-ng-click="addNew()">Add New Workboard</button>
</div>
</div>

If you want to add new elements after click you should extend the list which you are iterating. In your code for example if you change your code in the following way:
$scope.addNew = function(){
$scope.flag=true;
$scope.workboardStagesWithDefault.push({Name:"ButtonNew"});
};
You will be adding new position ButtonNew whenever you will click Add New Workboard button.

Related

Vue, changing the name of an input via list item click

I have an input that I'm using in relation two an unordered list with two list items, which is in place, but I"m trying to figure out how I can change the input name/id with the click of one of the list items.
The items are not links or buttons, so I just want to be able to click the item text and if 'Public' is clicked, the input name would become public, if 'Internal' is clicked I would want the input name to be internal
I'm using Vue which may have some better options, but basically I just want to send the name of the input later on in an ajax call and I only want the name to be determined by the click of a list item potentially with a default.
What is the best way to achieve this with Vue being used?
<div class="row notesInput">
<div class="col-lg-12">
<div class="tabs">
<ul style="border-bottom:none !important; text-decoration:none">
<li>Public</li>
<li>Internal</li>
</ul>
</div>
<div>
<input type="text" name="public">
</div>
</div>
</div>
First step: use component data to your advantage
You can simply store the desired input name attribute in the component data, e.g. inputName. Then, use v-on to bind a click event listener to your elements, so that whenever they are clicked, you invoke a method that updates the inputData property of your component.
new Vue({
el: '#app',
data: {
inputName: '',
},
methods: {
setInputName(str) {
this.inputName = str;
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<div class="row notesInput">
<div class="col-lg-12">
<div class="tabs">
<ul style="border-bottom:none !important; text-decoration:none">
<li v-on:click="setInputName('public')">Public</li>
<li v-on:click="setInputName('internal')">Internal</li>
</ul>
</div>
<div>
<input type="text" v-bind:name="inputName">
<br />
Input name attribute is: {{ inputName }}
</div>
</div>
</div>
</div>
Better: Use v-for to generate list items dynamically
If you don't want the manually provide the argument to the method, there's an easier way: you simply create a list of allowed names in the component data, too, and use v-for to generate the list dynamically:
new Vue({
el: '#app',
data: {
inputName: '',
allowedNames: ['Public', 'Internal']
},
methods: {
setInputName(str) {
this.inputName = str.toLowerCase();
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<div class="row notesInput">
<div class="col-lg-12">
<div class="tabs">
<ul style="border-bottom:none !important; text-decoration:none">
<li
v-for="(allowedName, i) in allowedNames"
v-bind:key="i"
v-on:click="setInputName(allowedName)">
{{ allowedName }}
</li>
</ul>
</div>
<div>
<input type="text" v-bind:name="inputName">
<br />
Input name attribute is: {{ inputName }}
</div>
</div>
</div>
</div>
Even better: if there is no one-to-one correspondance between list item text and the desired name attribute
This can be useful in the case when, for example, you want the text to read Public but the name attribute to be another value. Instead of an array of strings, you can use an array of objects:
new Vue({
el: '#app',
data: {
inputName: '',
allowedNames: [{
label: 'Public (or any other arbitrary text you like)',
name: 'public'
}, {
label: 'Internal (or any other arbitrary text you like)',
name: 'internal',
}]
},
methods: {
setInputName(str) {
this.inputName = str;
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<div class="row notesInput">
<div class="col-lg-12">
<div class="tabs">
<ul style="border-bottom:none !important; text-decoration:none">
<li
v-for="(allowedName, i) in allowedNames"
v-bind:key="i"
v-on:click="setInputName(allowedName.name)">
{{ allowedName.label }}
</li>
</ul>
</div>
<div>
<input type="text" v-bind:name="inputName">
<br />
Input name attribute is: {{ inputName }}
</div>
</div>
</div>
</div>

Selecting first tab by default when page is loaded in angularJS

I have the following angular code for showing student info in the tabbed format.
Following is the student.html class
<div class="panel panel-default">
<ul class="nav nav-tabs">
<li ng-repeat="studentTab in studentList"
ng-class="{active: selectedStudentTab.name === studentTab.name}">
<a ng-click="selectStudentTab(studentTab)">{{studentTab.name}}</a>
</li>
</ul>
<div class="panel-body">
<div class="tab-content">
<div class="tab-pane active" ng-repeat="studentTab in studentList"
ng-show="selectedStudentTab.name === studentTab.name">
<div style="padding: 35px; text-align: left;">
<div ng-repeat="project in studentTab.projects">
<p><pre>{{project.log}}</pre></p>
</div>
</div>
</div>
</div>
</div>
</div>
in my studentController.js I have assigned the oth element of studentList to the tab, following is the code:
$scope.init = function () {
$rootScope.initOrRedirectToLandingPage($scope.loadStudents);
};
$scope.studentList = [];
$rootScope.loadStudents = function(){...
};
$scope.selectedStudentTab = $scope.studentList[0];
$scope.selectStudentTab = function (studentTab) {
$scope.selectedStudentTab = studentTab;
};
Here the tabs are created properly, but the first tab is not selected/active by default on loading of the page and becomes active only on the click event.
Can someone help me to figure out what am I missing? any help is appreciated.
In your controller after you load the studentList assign the selectedStudentTab to the first item in the list.
$scope.studentList = [...];
$scope.selectedStudentTab = $scope.studentList[0];

ng-model taking for all inputs after clicking edit

I am using AngularJS. I am generating pipeline-like structure. At first onload I am having one default ng-repeat value. After clicking "add more" I am displaying another list. It goes on adding as long as I am clicking the "add" button.
Here is my HTML:
Add button
<button data-ng-click="addNew()">Add New Workboard</button>
New pipeline will be created with Pipeline Names and one text box to add stageNames
<div data-ng-show="listOfLists.length > 0">
<div data-ng-repeat="list in listOfLists">
<div data-ng-repeat="pipeline in workboardstages track by $index">
<div class="added-eachboard">
<div class="form-group">
<input name="pipelineName" id="pipelineName" data-ng-
model="pipeline.pipelineName" type="text">
</div>
<ul class="simpleDemo workboard-drags" data-ng-repeat="(key,
workboardlist) in pipeline.workBoardStageMap">
<li data-ng-if="pipeline.pipelineName == key" ng-repeat="workboard in
workboardlist">{{workboard.stageName}}
<a href ="javascript:void(0)" data-ng-
click="editWorkboardStage(workboard.stageId)"><img src =
"resources/zingy/images/Edit-Small.png" class="TableIcon"></a>
</li>
</ul>
<div>
<p class="weak">Stage Name:</p>
<div class="form-group">
<input name="stageName" id="stageName" data-ng-
model="newworkboard.stageName" type="text">
</div>
</div>
</div>
</div>
</div>
</div>
Controller.js
$scope.listOfLists = [];
$scope.workboardStagesWithDefault = [
{
Name:"Test"
},
{
Name:"Test2"
},
{
Name:"Test3"
}
];
$scope.addNew = function(){
var clonedList = angular.copy($scope.workboardStagesWithDefault);
$scope.listOfLists.push(clonedList);
};
$scope.editWorkboardStage = function(stageId){
AccountService.editWorkboardStage(stageId).then(function(response){
$scope.newworkboard = response.data;
});
}
$scope.getAllWorkboardStages = function(){
AccountService.getAllWorkboardStages().then(function(response){
$scope.workboardstages = response.data;
$scope.listOfLists.push($scope.workboardstages);
});
}
After clicking edit i am displaying stage name in that particular text box.But the problem is it is displaying same for neighbouring pipeline also.I want to display only for that current pipeline.As i am displaying using ng-model it is taking for all pipelines.How to display the value only for that particular pipeline?
So, the problem is related to indexing. I made $scope.newworkboard index wise.
This is the solution: (newworkboard is based on pipeline index and pass index from editWorkboardStage function.)
<input name="stageName" id="stageName" data-ng-model="newworkboard[$index].stageName" type="text">
AND
<a href ="javascript:void(0)" data-ng-click="editWorkboardStage(workboard.stageId, $parent.$parent.$index)"><img src =
"resources/zingy/images/Edit-Small.png" class="TableIcon"></a>
HTML
<div data-ng-show="listOfLists.length > 0">
<div data-ng-repeat="list in listOfLists">
<div data-ng-repeat="pipeline in workboardstages track by $index">
<div class="added-eachboard">
<div class="form-group">
<input name="pipelineName" id="pipelineName" data-ng-
model="pipeline.pipelineName" type="text">
</div>
<ul class="simpleDemo workboard-drags" data-ng-repeat="(key,
workboardlist) in pipeline.workBoardStageMap">
<li data-ng-if="pipeline.pipelineName == key" ng-repeat="workboard in
workboardlist">{{workboard.stageName}}
<a href ="javascript:void(0)" data-ng-
click="editWorkboardStage(workboard.stageId, $parent.$parent.$index)"><img src =
"resources/zingy/images/Edit-Small.png" class="TableIcon"></a>
</li>
</ul>
<div>
<p class="weak">Stage Name:</p>
<div class="form-group">
<input name="stageName" id="stageName" data-ng-
model="newworkboard[$index].stageName" type="text">
</div>
</div>
</div>
</div>
</div>
</div>
Controller
In the controller make an array of newworkboard and assign response.data index wise.
$scope.newworkboard = [];
$scope.editWorkboardStage = function(stageId, index){
AccountService.editWorkboardStage(stageId).then(function(response){
$scope.newworkboard[index] = response.data;
});

LightGallery with JqueryMobile

I have a little problem with LightGallery plugin (lightGallery - Git). I use jQueryMobile.
My gallery is on a specific page. When I arrive on this page, it will request a remote server to get some pics.
Then I initialize LightGallery. No problem the first time.
But when I leave the Gallery Page and come back after (there is a new request to server), lightGallery is not running.
No error in the browser, I have my photos displayed but I can't click on it to run LightGallery like I've done the first time.
My Code:
HTML:
<div data-role="page" id="pageGallery" data-theme="a">
<div data-role="content" class="center-body">
<h3 class="nomGroupe"></h3><br/>
<div class="demo-gallery">
<ul id="lightgallery" class="list-unstyled row">
</ul>
</div>
</div>
</div>
Javscript :
$( document ).on( "pagecontainerbeforeshow", function ( event, ui ) {
var activePage = $.mobile.pageContainer.pagecontainer( "getActivePage" );
if (activePage[0].id == "pageGallery" ) {
$('#lightgallery').empty();
$(".groupName").empty().append("group "+localStorage['groupName']);
envoieRequete('http://myServer/', {'idGroup' : localStorage['idGroup'], 'token' : localStorage['token']}, 'post', function(output){
if(output.group.photos.length === 0) {
$("#lightgallery").append('<br/><p>Empty for Group : ' + localStorage['groupName']+'</p>');
}
else {
for(i=0; i<output.group.photos.length; i++) {
$('#lightgallery').append('<li class="col-xs-6 col-sm-4 col-md-3" data-responsive="http://myServer/'+localStorage['token']+'/'+localStorage['idGroup']+'/' + output.group.photos[i].id
+ '" data-src="http://myServer/'+localStorage['token']+'/'+localStorage['idGroup']+'/' + output.group.photos[i].id + '" data-sub-html="<h4>PhotoAlt</H4>"><a href=""><img class="img-responsive"\n\
src="http://myServer/'+localStorage['token']+'/'+localStorage['idGroup']+'/' + output.group.photos[i].id + '"/></a></li>');
}
}
});
}
});
$(document).on("pagecontainershow", function () {
var activePage = $.mobile.pageContainer.pagecontainer("getActivePage");
var activePageId = activePage[0].id;
switch (activePageId) {
case 'pageGallery':
$(document).on("tap", "#lightgallery li", function (){
$('#lightgallery').lightGallery({});
});
}
});
You might be using wrong html markup. you can check the following code for reference. This is sample code.
HTML
<div class="row">
<div class="large-12 columns">
<ul class="small-block-grid-2 medium-block-grid-3" id="lightgallery">
<li> <a class="item" href="img/alchemy_icon1.jpg"><img src="img/alchemy_icon1_th.jpg"></a>
</li>
<li> <a class="item" href="img/chandra1.jpg"><img src="img/chandra1-th.jpg"></a>
</li>
<li> <a class="item" href="img/Fish.jpg"><img src="img/Fish-th.jpg"></a>
</li>
</ul>
</div>
</div>
Javascript
$("#lightgallery").lightGallery({
selector: '.item'
});

passing html values to javascript functions

I have a ng-repeat in my view and I want to pass the object from my ng-repeat to a javascript function but when I try to display it on the console it gives me undefined.
Here is my html:
<!-- Panel -->
<div class="row">
<div class="col-lg-12">
<div class="panel panel-primary">
<div class="panel-heading">
{{card}}
</div>
<!-- /.panel-heading -->
<div class="panel-body">
<div id="nvd3-container" class="md-card" style="overflow-x: auto" ng-if="dataloaded0">
<md-card-content id="nvd3-scrollable-content" style="width: {{width}}px; height: 350px;">
<md-tabs md-dynamic-height="" md-border-bottom="">
<md-tab ng-repeat="pu in selectedKpi" label="{{pu.dprdProuNr}}">
<md-content class="md-padding">
<div class="row">
<div class="col-md-6">
{{pu.item1}}
{{pu.item2}}
</div>
</div>
</md-content>
</md-tab>
</md-tabs>
</md-card-content>
</div>
</div>
<!-- /.panel-body -->
<a href="" ng-click="footerLinkClicked(pu)">
<div class="panel-footer">
<span class="pull-left">Trend</span>
<span
class="pull-right">
<i class="fa fa-arrow-circle-right"></i>
</span>
<div class="clearfix"></div>
</div>
</a>
</div>
</div>
</div>
<!-- /.panel -->
Here is my js file that returns undefined:
angular.module('App')
.directive('KpiParameter', function() {
return {
restrict: 'E',
templateUrl: 'app/kpi/kpi-parameter/kpi-parameter.html',
scope: {
card: '=',
kpiParamCallback: '&',
selectedProductionUnit: '<'
},
controller: function($scope, $rootScope, KpiChartFactory, $filter) {
console.log("!???????");
console.log($scope.selectedProductionUnit);
$scope.$watch('selectedProductionUnit', function() {
console.log($scope.selectedProductionUnit);
console.log("Changed");
KpiParamUpdated();
$scope.kpiParamCallback({
selectedProductionUnit: $scope.productionUnitDefault
});
}, true);
function KpiParamUpdated() {
console.log("KPiParamUpdated");
console.log($scope.selectedProductionUnit);
$scope.dataloaded0 = true;
KpiChartFactory.get({ pu: $scope.selectedProductionUnit }, function(data) {
$scope.selectedKpi = data;
console.log($scope.selectedKpi);
$rootScope.$broadcast('kpiParams', $scope.selectedKpi);
});
}
$scope.footerLinkClicked = function(pu) {
console.log("parameters received :");
console.log(pu);
}
},
controllerAs: "KpiPCtrl"
};
});
Do you have any idea why? I need to define it also in my js file?
As found in the docs of AngularMaterial, you can only achieve what you want to do by using md-on-select
Attributes
Parameter Type Description
label string
Optional attribute to specify a simple string as the tab label
ng-disabled boolean If present and expression evaluates to truthy, disabled tab selection.
md-on-deselect expression Expression to be evaluated after the tab has been de-selected.
md-on-select expression Expression to be evaluated after the tab has been selected.
md-active boolean When true, sets the active tab. Note: There can only be one active tab at a time.
Note: This event differs slightly from ng-click, in that if a tab is already selected and then clicked, the event will not fire.
Your call to footerLinkClicked() has no way of knowing which pu to use unless you tell it which one to use. And since it's outside of your ng-repeat, there's no overly easy way to do that.
md-tabs has an attribute called md-selected that allows you to store the currently selected index in a variable. So assuming that selectedKpi is an array (or is array-like), you can do this:
<md-tabs md-dynamic-height="" md-border-bottom="" md-selected="selectedTab">
and this:
<a href="" ng-click="footerLinkClicked(selectedKpi[selectedTab])">
and you should be all set.