Repeat html code onpush of button in angular - angularjs

I have a simple ng-click button at the moment that adds rows with the row and number.
What im wanting is to add a new segment of code which is this:
<div class="btn btn-info btn-sm" style="display:inline-block" ngf-select="uploadinv($file)">Upload Attachment</div>
<p style="display:inline-block;" ng-if="filenameinv">Uploaded file</p>
<button type="button" ng-click="deleteAtt(file)" class="btn btn-danger btn-sm">
<i class="fa fa-trash-o"></i>
</button>
<button type="button" ng-click="addAtt()" class="btn btn-info btn-sm">
<i class="fa fa-plus"></i>
</button>
Heres what i have in my controller
$scope.rows = ['Row 1', 'Row 2'];
$scope.counter = 3;
$scope.addAtt = function() {
$scope.rows.push('Row ' + $scope.counter);
$scope.counter++;
};
I'm wanting to adapt the controller code to make it work with copying the code above up to 5 items. And ideally on each new item the plus button from the previous would disappear so there would always only be one button.
Basically at the moment there is one upload button. With a delete and plus button that appears when a file is uploaded. What i'm wanting is when a user wants to upload another file said user can click the plus button and another uploader will appear. I also need to get this saving against the db but thats another headache!
Heres the uploader
$scope.uploadinv = function (file) {
if (file) {
Upload.upload({
url: '',
data: {file: file}
}).then(function (resp) {
sweetAlert({title: "Attachment Saved", type: "success"});
}, function (resp) {
sweetAlert({title: "Attachment Not Saved", type: "error"});
}, function (evt) {
var progressPercentage = parseInt(100.0 * evt.loaded / evt.total);
console.log('progress: ' + progressPercentage + '% ' + evt.config.data.file.name);
$scope.event.filenameinv = evt.config.data.file.name
});
}
};
This is the bit i've done so far
$scope.fileUploadRows = [];
var fileDetails = {
fileName: $scope.event.filenameinv
}
$scope.fileUploadRows.push(fileDetails);
$scope.counter = 1;
$scope.addInvAttachment = function() {
var fileDetails = {
fileName: $scope.event.filenameinv
}
$scope.fileUploadRows.push(fileDetails);
$scope.counter++;
}

May be this could help:
<div class="row" ng-repeat="row in rows track by $index">
<div class="btn btn-info btn-sm" style="display:inline-block" ngf-select="uploadinv($file)">Upload Attachment</div>
<p style="display:inline-block;" ng-if="fileUploadRows[$index].filename">Uploaded file</p>
<button type="button" ng-click="deleteAtt(file)" class="btn btn-danger btn-sm">
<i class="fa fa-trash-o"></i>
</button>
<button type="button" ng-if="$last" ng-click="addAtt()" class="btn btn-info btn-sm">
<i class="fa fa-plus"></i>
</button>
</div>
Please note that you probably should handle (array of) filenameinv somehow. You didn't show in your code how you use/intialize this variable.
EDIT: See updated markup above. The trick is to have the appropriate $index. I think you should also call addInvAttachment() function, probably in the sucess then of the upload.

Related

AngularJS table flickers

I have a simple AngularJS app that shows a table with data on an ng-repeat after the user logins. I'm having an issue where after logging in, the table briefly shows blank rows and then the actual rows with data. Any suggestions on how to fix this?
This is the controller for the login:
$scope.login = function(user) {
loginSrvc.login(user).then(function(response) {
if (response == "authentication failed") {
$scope.error = true;
$scope.user = {};
$location.path("/");
} else {
if (response.group_name == "On Site Registration"){
var data = {
event: response.zk_event_id,
group: response.zk_group_id
};
$scope.getAvailableCamper(data);
}
else if (!response.zk_group_id) {
$location.path("/form/" + response.zkp_camper_id);
}
else {
$location.path("/dashboard/" + response.zk_event_id + "/" + response.zk_group_id);
}
}
})
}
$scope.getAvailableCamper = function(data) {
dashboardSrvc.fetchGroup(data).then(function(response){
var findAvailableCamper = _.find(response.data, {status: null});
console.log("this is find", findAvailableCamper);
var id = findAvailableCamper.zkp_camper_id;
$location.path("/onSiteForm/" + id);
})
}
This is the controller for the table:
$scope.campers = function() {
$scope.camper = loginSrvc.getCampers();
}
$scope.campers();
$scope.fetchCampers = function(id) {
dashboardSrvc.fetchCampers(id).then(function(response){
$location.path("/form/" + id);
})
}
Here's the html code for table:
<tr ng-repeat="campers in camper">
<td>{{$index + 1}}</td>
<td>{{campers.name_first}}</td>
<td>{{campers.name_last}}</td>
<td><button type="submit" name="submit" ng-click="register(campers)" class="btn btn-success" role="button" ng-hide="campers.status == 'Submitted' " ng-disabled="!(!!campers.name_first && !!campers.name_last && !!campers.gender && !!campers.city && !!campers.date_of_birth && !!campers.email && !!campers.emergency_cell_phone && !!campers.emergency_contact_first_name && !!campers.emergency_contact_last_name && !!campers.emergency_home_phone && !!campers.relationship_to_camper && !!campers.first_time_flag )">Submit</button> <p ng-show ="campers.status == 'Submitted'" > {{campers.registration_date | date: 'medium'}}
</p>
</td>
<td>{{campers.status}}</td>
<td>
<button ng-click="fetchCampers(campers.zkp_camper_id)" type="submit" name="view" class="btn btn-default" role="button" ng-show="campers.status == 'Submitted' "><span class="glyphicon glyphicon-eye-open"></span></button>
<button ng-click="fetchCampers(campers.zkp_camper_id)" type="submit" name="edit" class="btn btn-default" role="button" ng-hide="campers.status == 'Submitted' " ><span class="glyphicon glyphicon-edit"></span></button>
<button type="button" ng-click="setValue(campers.zkp_camper_id)" name="deleteModalLauncher" id="deleteModalLauncher" class="btn btn-danger" role="button" data-toggle="modal" data-target="#deleteModal" ng-hide="campers.status == 'Submitted' " ><span class="glyphicon glyphicon-trash" aria-hidden="true"></span></button>
</td>
</tr>
I really appreciate the help! Thanks!
There is a directive to minimize flickering that angular loop does while check bindings and all. it is called ng-cloak and it can be added to any element on your view.
More info : https://www.w3schools.com/angular/ng_ng-cloak.asp
...
You can also use angularjs event who is fired when content is fully loaded and set a flag ex. loaded = true and then use ng-show with loaded variable.
Controller :
$scope.$on('$viewContentLoaded', function(){
$scope.loaded = true;
});
View :
<table ng-show="loaded">
.....
</table>
Hope that helps!

how to refresh the list in AngularJs?

I have to implement the share product functionality with the user after share i have to refresh the list here selectedSharedIntermediaryInAlbum is our array so how to implement this?
//refreshSharedIntermediary for refresh the lsit
$scope.refreshSharedIntermediary = function() {
$scope.selectedSharedIntermediaryInAlbum = $scope.selectedSharedIntermediaryInAlbum;
}
<div class="w3-right">
<button class="btn btn-rose btn-sm" tltle="refresh data" ng-click="refreshSharedIntermediary()">
<i class="glyphicon glyphicon-repeat"></i>
</button>
</div>
You can use $scope.reload function where need to reload the list ... i have used below concept :
<div class="well well-lg" ng-repeat="item in list track by item.id">
<button class="btn btn-default"
ng-click="collapsedFlags[item.id] = !collapsedFlags[item.id]">
{{ item.isCollapsed ? '+' : '-' }}
</button>
<div uib-collapse="collapsedFlags[item.id]" ng-bind="item.value"></div>
</div>
$scope.reload = function () {
$http.get('list.json').then(function (data) {
$scope.list = data && data.data || [];
});
};
$scope.collapsedFlags = {};
$scope.reload();
Working example : https://plnkr.co/edit/87vVb8Jjyz6yFGAjiHBK?p=preview

Angular ng-click function requiring two clicks to take effect

I have the following directive
app.directive('replybox', function ($timeout, $window, $compile, $sce) {
var linkFn = function (scope, element, attrs) {
var exampleText= element.find('p');
var btn = element.find('button');
var windowSelection="";
scope.okOrCancel="None";
exampleText.bind("mouseup", function () {
scope.sel = window.getSelection().toString();
windowSelection=window.getSelection().getRangeAt(0);
if(scope.sel.length>0) {
scope.showModal = true;
scope.$apply();
}
});
btn.bind("click", function () {
if(scope.okOrCancel=='ok'){
range = windowSelection;
var replaceText = range.toString();
range.deleteContents();
var div = document.createElement("div");
div.innerHTML = '<poper>' + replaceText + '<button type="button" class="btn btn-danger btn-xs">×</button></poper>';
var frag = document.createDocumentFragment(), child;
while ((child = div.firstChild)) {
frag.appendChild(child);
}
$compile(frag)(scope);
range.insertNode(frag);
scope.showModal=false;
}
if(scope.okOrCancel=='cancel'){
scope.showModal=false;
}
scope.selection="None";
scope.okOrCancel='None';
});
};
return {
link: linkFn,
restrict: 'A',
scope: {
entities: '=',
selection:'='
},
template: `<ng-transclude></ng-transclude>
<div class="modal fade in" style="display: block;" role="dialog" ng-show="showModal">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-body">
{{sel}}
</div>
<div class="radio">
<div ng-repeat="x in entities">
<div class="radio">
<label>
<input type="radio" name="choice" ng-model="$parent.selection" ng-value = "x">
{{x}}
</label>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-primary" ng-click="okOrCancel='ok'">
Ok
</button>
<button type="button" class="btn btn-primary" ng-click="okOrCancel='cancel'">
Cancel
</button>
</div>
</div>
</div>
</div>`,
transclude: true
};
});
So there is a modal in the template which contains an "Ok" and a "Cancel" button. There is an ng-click on these buttons which sets scope.okOrCancel to the appropriate value. btn binds to a button click and performs different actions depending on the state of scope.okOrCancel. When the "Ok" button is clicked everything works as expected. But the "Cancel" button requires two clicks in order for the modal to dissappear. I would think this would happen immediately within
if(scope.okOrCancel=='cancel'){
scope.showModal=false;
}
Can anyone tell me why the cancel button requires two clicks to close the modal?
Currently you have a mix of jQuery and angularjs for your ok and cancel click. Probably that is the reason to require two clicks to take effect.
If I were you, I would have write click like below:
Template:
<div class="modal-footer">
<button type="button" class="btn btn-primary" ng-click="okClick()"> Ok </button>
<button type="button" class="btn btn-primary" ng-click="cancelClick()"> Cancel </button>
</div>
In JS:
scope.okClick = function() {
range = windowSelection;
var replaceText = range.toString();
range.deleteContents();
var div = document.createElement("div");
div.innerHTML = '<poper>' + replaceText + '<button type="button" class="btn btn-danger btn-xs">×</button></poper>';
var frag = document.createDocumentFragment(), child;
while ((child = div.firstChild)) {
frag.appendChild(child);
}
$compile(frag)(scope);
range.insertNode(frag);
scope.showModal=false;
}
scope.cancelClick = function() {
scope.showModal=false;
}
scope.selection="None";
scope.okOrCancel='None';
I hope this helps you!
Cheers
Completely agree with varit05's answer. Most likely it's because you do not trigger digest cycle in the click event handler. But in any way, the point is: it's not very good idea to mix jquery and angular stuff, unless: a) you absolutely sure it's necessary; b) you understand very well what you're doing and why; otherwise it will lead to such an unexpected consequences.
Just another a small addition. Another problem is here:
$compile(frag)(scope);
range.insertNode(frag);
The correct approach would actually be to insert new nodes into real DOM and only then $compile() them. Otherwise, any directives with require: "^something" in the DOM being inserted will fail to compile because they would not be able to find necessary controllers in upper nodes until new nodes actually make it to the "main" DOM tree. Of course, if you absolutely sure you don't have that then you can leave it as is and it will work... But then the problem will just wait out there for its "finest hour".

ng-click of angularJS is not displaying anything when buttons are clicked

angular js code:
appModule.controller('dcrlistingCtrl', ['$scope','$modal','$state','$rootScope','loginService', 'servicePOST', 'appConstants','sessionService', '$http',
function($scope,$modal,$state,$rootScope,loginService, servicePOST, appConstants,sessionService, $http) {
$scope.doctors = function() {
alert("Doctors");
};
$scope.pharmacists = function() {
alert("pharmacists");
};
$scope.stockists = function() {
alert("pharmacists");
};
alert("trial");
$scope.contact="Doctors";
$scope.doctors=
[
{"patch":"BARIJPUR", "doctor":["RAMA SENA", "SMRITI IRANI","JAGDISH NAIR"]},
{"patch":"Anna", "doctor":["ASHISH NAIK", "SMRITI IRANI", "SAIRAJ NAIK"]},
{"patch":"Peter","doctor":["RATAN PANDEY", "RAMAN SHIVOLKAR"]}
];
}])
html code:
<button type="button" class="btn btn-primary " ng-click=="doctors()"><b>Doctor</b></button>
<button type="button" class="btn btn-primary " ng-click=="pharmacists()" ><b>Pharmacist</b></button>
<button type="button" class="btn btn-primary " ng-click=="stockists()" ><b>Stockist</b></button>
any angularJS experet here? need help!
the alert("trial"); is shown!
But when i click these buttons, no alert is shown!
why is that so?
any help and advice or changes are appreciated!
Get rid of the double equals after each ng-click.
The following:
ng-click=="stockists()"
should be
ng-click="stockists()"
The alert("trial") is being shown because it is not within the scope
of any click function of yours rather in the scope of controller where
the alert("trial") gets called once you are into the view which has
that particular controller. And, the matter of fact where your click
function is not working is because you have got 2 equals(==) in
ng-click.
<button type="button" class="btn btn-primary " ng-click="doctors()"><b>Doctor</b></button>
<button type="button" class="btn btn-primary " ng-click="pharmacists()" ><b>Pharmacist</b></button>
<button type="button" class="btn btn-primary " ng-click="stockists()" ><b>Stockist</b></button>

AngularJS - showing an item only if none of the booleans in a collection are true

I would like to show the button in the code only if none of the aspects in $scope.aspects are true.
<aspect-form ng-repeat="aspect in aspects | filter:{active: true}">
</aspect-form>
<a class="btn btn-primary btn-lg" role="button">Save</a>
How would I do this?
You can do it without binding to a function on the scope like this:
<a class="btn btn-primary btn-lg"
ng-if="(aspects | filter:{active: true}).length === 0">Save</a>
In situations like these I like to use the array.every() and array.some() functions:
<a class="btn btn-primary btn-lg" role="button" ng-if="allAspectsFalse()">Save</a>
$scope.allAspectsFalse = function() {
return $scope.aspects.every(function(aspect) {
return !aspect.active;
});
}
You can use ng-if in the a element, and give it a function that evaluates to true only when all of the aspects in $scope.aspects are false.
<a class="btn btn-primary btn-lg" ng-if="allAspectsAreFalse()">Save</a>
I also found a solution. Mine is using ng-show instead but is practically the same. I will show the whole solution.
<a class="btn btn-primary btn-lg" role="button" ng-show="someAspectShowing()">Save</a>
and in the controller I have defined the function:
$scope.someAspectShowing = function() {
for(index=0; index < $scope.aspects.length; ++index) {
if($scope.aspects[index].active === true) {
return true;
}
}
return false;
};

Resources