In a datatable how to pass a data value to a function here i am using two variables (newId , orderId ) and both are showing value in console but when i pass the value to a button on click function(renderViewDetails) it is saying variable(newId or orderId) it is undefined so what should i do to pass the value to a function on button click?
{
data: null,
orderable: false,
className: 'text-center',
render: function (data, type, row, ) {
var newId = data.id;
console.log(221, newId);
let orderId = `${data.id}`;
console.log(223, orderId);
let selDropdown = `<div class= flex-button> <div>
<a href="" id="" class="" data-toggle="modal" data-target="#view-details-modal">
<button id="btnViewConcepts" class="btn-link" type=""button" onclick="renderViewDetails(orderId)">View Details</button>
</a>
</div> <div id="setOption">`
}
Although you are doing the right thing by using template literal (backtick) for your HTML string, when you pass your variable you are passing a string of the variable name instead of its value. Instead, enclose the variable with curly braces with a $ sign in front.
let selDropdown = `<div class= flex-button> <div>
<a href="" id="" class="" data-toggle="modal" data-target="#view-details-modal">
<button id="btnViewConcepts" class="btn-link" type=""button" onclick="renderViewDetails(${orderId})">View Details</button>
</a>
</div> <div id="setOption">`
let selDropdown = `<div class= flex-button> <div>
<a href="" id="" class="" data-toggle="modal" data-target="#view-details-modal">
<button id="btnViewConcepts" class="btn-link" type=""button" onclick=${renderViewDetails(orderId)}>View Details</button>
</a>
</div> <div id="setOption">`
Related
var id = '';
var result=[];
var url = "http://www.omdbapi.com/?type=movie&apikey="+api_key;
function handle(e){
if(e.keyCode === 13){
$("#form1").submit(function(event){
event.preventDefault();
})
var search_value = $("#search").val();
if(search_value==""){
alert("Please enter a movie name!")
}
else{
$.ajax({
method: "GET",
url: url+"&t="+search_value,
success: function(data){
id = data.Title
result.push(`<div class="container resultcont">
<img src="${data.Poster}" class="img-thumbnail poster float-left" width="150px" height="150px"/>
<p>Title: ${data.Title}</p>
<p> Genre: ${data.Genre}</p>
<p> Release Date: ${data.Released}</p>
<p> Runtime: ${data.Runtime}</p>
<p>Ratings: ${data.imdbRating}</p>
<button class="btn btn-dark btn-block" id="wlbtn ${id}" onclick="watchlist()">Add</button>
</div>
<br>`)
parameter = parameter + `<div class="container resultcont">
<img src="${data.Poster}" class="img-thumbnail poster float-left" width="150px" height="150px"/>
<p>Title: ${data.Title}</p>
<p> Genre: ${data.Genre}</p>
<p> Release Date: ${data.Released}</p>
<p> Runtime: ${data.Runtime}</p>
<p>Ratings: ${data.imdbRating}</p>
</div>
<br>`
$("#searchresultdiv").html(result)
}
})
}
}
}
function watchlist(){
document.getElementById(id).setAttribute("style","display:none")
var remove_btn = `<button class="btn btn-dark btn-block" float="right" id="wlbtn" onclick="removewatchlist()">Remove</button>`
$("#watchlistdiv").html(parameter+remove_btn)
}
I am pushing the search results into the result array. So each result is in a div resultcont.
So the problem i have is, I want to do some manipulation specific to the resultcont's button. For example:
So if i click on hulk's add button, only that div should get added to watchlist. How to only add hulk's div without adding avenger's div
First I would not recommend that you have space in your ID so wlbtn ${id} becomes wlbtn_${id}
Second inside your watchlist function you use ID but the function don't know the reference to ID same goes for parameter
function watchlist(obj) {
$(obj).prop("disabled", true);
var remove_btn = `<button class="btn btn-dark btn-block" float="right" id="wlbtn" onclick="removewatchlist()">Remove</button>`
$(obj).after(remove_btn)
}
Demo
function watchlist(obj) {
$(obj).hide()
var remove_btn = `<button class="btn btn-dark btn-block" float="right" id="` + $(obj).attr("id") + `_remove" onclick="removewatchlist(this)">Remove</button>`
$(obj).after(remove_btn)
$(obj).closest(".card").appendTo(".watchlist");
}
function removewatchlist(obj){
$(obj).closest(".card").remove()
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="card">
<div>HULK</div>
<button class="btn btn-dark btn-block" id="wlbtn_1" onclick="watchlist(this)">Add hulk</button><br>
</div>
<div class="card">
<div>AVENGERS</div>
<button class="btn btn-dark btn-block" id="wlbtn_2" onclick="watchlist(this)">Add Avengers</button><br>
</div>
<div class="watchlist">
<h2>Watchlist</h2>
</div>
I generated a random number called listingid in function createpost and pass it as an input to function showproductmodal as shown below
function creatpost(){
var index;
splitinput.forEach((num, index) => {
var listingid = (Date.now().toString(36) + Math.random().toString(36).substr(2, 5)).toUpperCase()
console.log(index)
return CatalogueDB.ref( splitinput[index]).once('value').then(function(snapshot) {
var resultcard = `
<form id="myform${index}">
<tr class="tr-shadow">
<td>
<button type="button" class="btn btn-primary btn-md" onclick="postitem(${key},${index},${listingid});">Submit</button>
</td>
</tr>
</form>
`
container.innerHTML += resultcard;
})
.catch(function(error) {
container.innerHTML += "";
var errorcard = `
<form id="myform${index}">
<tr class="tr-shadow">
<td style="width: 90px;">
<div id="ItemID${index}">${splitinput[index]}
</div>
<div>
<br>
<button type="button" class="btn btn-secondary mb-1 btn-sm" data-toggle="modal" data-target="#productModal" onclick="showproductmodal(${splitinput[index]},${index},${listingid})">
Add Photos
</button>
</div>
</td>
<td>
<button type="button" class="btn btn-primary btn-md" onclick="postitem(${splitinput[index]},${index},${listingid})">Submit</button>
</td>
</tr>
</form>
`
container.innerHTML += errorcard;
})
});
})
function showproductmodal(id, index, listingid) {
console.log(id,index)
}
the problem now is whenever the button is clicked which triggers showproductmodal it says lisitingid is undefined
this is the console error output
index.html:1 Uncaught ReferenceError: JJLQ23008PJX0 is not defined
at HTMLButtonElement.onclick (index.html:1)
this is the sample parameters passed to the showproductmodal retrieved from the console
showproductmodal(42,0,JJLQ23008PJX0)
why is the listingid causing error even when it has been passed to the function? How do I correct this so that I can retrieve listingid in showproductmodal?
If the listingid is not a variable with the name JJLQ23008PJX0 it will throw an error.
Generally one need to make such id/value be treated as a string, and enclose it in quotes, likes this, where I added single quote's '
onclick="postitem(${splitinput[index]},${index},'${listingid}')"
Some value types works though, as numbers, the boolean keywords true/false, etc.,
You need to quote the random string:
<button type="button" class="btn btn-primary btn-md" onclick="postitem(${key},${index},'${listingid}');">Submit</button>
I'm building an app that can upload multiple images at once with vue.js. At the #change event of the file input (when i select files to be uploaded), i want a preview and name of the selected images and then a button to cancel individual files. All that works fine. However, when i try to cancel any of the images with the button, only the name gets deleted, the image remains. Can someone kindly guide me in correcting what i'm doing wrong. The issue seems to be with my cancelImage method.
My template:
<div class="form-group">
<textarea name="body" class="form-control" v-model="body"></textarea>
</div>
<div class="form-group">
<label class="control-label">Files
<input type="file" ref="files" accept="image/*" multiple="multiple" #change="selectFiles">
</label>
</div>
<div v-for="(file, key) in files">
<img class="preview" v-bind:ref="'image' +parseInt( key )" />
 {{ file.name }}
<button type="button" class="btn btn-danger" #click.prevent="cancelImage(file, key)"> X </button>
</div>
<div class="form-group">
<button #click.prevent="addFiles" class="btn btn-default">Add Files</button>
</div>
<div class="form-group">
<button type="button" class="btn btn-primary btn-block" #click.prevent="upload">Upload</button>
</div>
and then my script:
export default {
data(){
return {
body: '',
files: [],
form: new FormData()
}
},
methods: {
uploadFiles(e){
let selectedFiles = e.target.files;
let vm = this;
for (let i=0; i < selectedFiles.length; i++){
vm.files.push(selectedFiles[i]);
}
this.imagePreview();
console.log(this.files)
},
imagePreview(){
let vm = this;
for (let i=0; i<vm.files.length; i++){
let reader = new FileReader();
reader.addEventListener('load', function(){
vm.$refs['image' + parseInt( i )][0].src = reader.result;
}.bind(vm), false);
reader.readAsDataURL(vm.files[i]);
}
},
addFiles(){
this.$refs.files.click();
},
cancelImage(file){
let index = this.files.indexOf(file);
this.files.splice(index, 1);
}
}
}
When using a v-for a an array, you can pass 2 arguments. The first is the item being iterated over, the second is the index of that item. So right now, this:
<div v-for="(file, key) in files">
<img class="preview" v-bind:ref="'image' +parseInt( key )" />
 {{ file.name }}
<button type="button" class="btn btn-danger" #click.prevent="cancelImage(file, key)"> X </button>
</div>
might not being doing exactly what you think. file is your item being iterated over (the pushed formData) and key is actually the index of the item in your files array. Typically, a key in a v-for is used to add unique identifiers to each element to help Vue know which element is which. You use that with the :key attribute (something like file.id or whatever prop would work for you as a unique ID). So try something like this:
HTML:
<div v-for="(file, index) in files" :key="file.name"> // This is a terrible key, but I am not sure what properties exist on your formData objects.
<img class="preview" v-bind:ref="'image' + index" />
 {{ file.name }}
<button type="button" class="btn btn-danger" #click.prevent="cancelImage(index)"> X </button>
</div>
JS:
cancelImage(index){
this.files.splice(index, 1);
}
Since the v-for is creating a button for each element in the array, this will pass the index to the cancelImage method and allow you to remove that specific element without having to first "find" the file's index.
Edit: Removed file from the cancelImage method, since only the index is needed.
I'm banging my head against the wall here. I'm using ng-repeat to populate a table. Inside each row i have 2 buttons, one for updating the row content and for uploading files. The upload button opens a bootstrap modal window, where the user selects the files and clicks on submit.
The submit button uses ng-click to run a function which uses $index as parameter. But the $index value is always the same no matter which row is selected.
The thing I don't understand is that I use the exact same syntax (although outside of a modal window) on my update button, which works just fine.
HTML:
<tr ng-repeat="item in items | filter:search " ng-class="{'selected':$index == selectedRow}" ng-click="setClickedRow($index)">
<td>{{$index}}</td>
<td ng-hide="idHidden" ng-bind="item.Id"></td>
<td ng-hide="titleHidden">
<span data-ng-hide="editMode">{{item.Title}}</span>
<input type="text" data-ng-show="editMode" data-ng-model="item.Title" data-ng-required />
<td>
<button type="button" class="btn btn-primary uploadBtn" data-ng-show="editMode" data-toggle="modal" data-target="#uploadModal">Upload file <i class="fa fa-cloud-upload"></i></button>
<!-- Upload Modal -->
<div class="modal fade" id="uploadModal" tabindex="-1" role="dialog" aria-labelledby="uploadModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h3 class="modal-title" id="uploadModalLabel">Options</h3>
</div>
<div class="modal-body">
<h4>Upload Documents</h4>
<form>
<div class="form-group">
<select data-ng-model="type" class="form-control" id="fileTypeSelect">
<option value="Policy">Policy</option>
<option value="SOP">SOP</option>
</select>
<br>
<div class="input-group"> <span class="input-group-btn">
<input type="file" id="file">
</span>
</div>
<br>
<button type="button" class="btn btn-default" data-ng-click="uploadAttachment($index, type)">Upload</button>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
</div>
<button type="button" data-ng-hide="editMode" data-ng-click="editMode = true;" class="btn btn-default pull-right">Edit <i class="fa fa-pencil-square-o"></i></button>
<button type="button" data-ng-show="editMode" data-ng-click="editMode = false; updateItem($index)" class="btn btn-default">Save</button>
<button type="button" data-ng-show="editMode" data-ng-click="editMode = false; cancel()" class="btn btn-default">Cancel</button>
</td>`
JS:
$scope.uploadAttachment = function executeUploadAttachment(index, type) {
var listname = "Risk Register";
var id = $scope.items[index].Id;
console.log(indexID);
readFile("uploadControlId").done(function(buffer, fileName) {
uploadAttachment(type, id, listname, fileName, buffer).done(function() {
alert("success");
}).fail(function() {
alert("error in uploading attachment");
})
}).fail(function(err) {
alert("error in reading file content");
});
}
So the function uploadAttachment($index, type) which is triggered by ng-click doesn't pass the right index number. It always passes the same, no matter what row it is clicked in.
I have omitted some of the code that is irrelevant. If needed i can provide the whole thing.
Any suggestions to what I am missing?
Edit:
I have tried to implement DonJuwe suggestions.
I have added this inside my controller:
$scope.openModal = function(index) {
var modalInstance = $modal.open({
templateUrl: 'www.test.xxx/App/uploadModal.html',
controller: 'riskListCtrl',
resolve: {
index: function() {
return index;
}
}
});
};
This is my modal template:
<div class="modal-header">
<h3 class="modal-title" id="uploadModalLabel">Options</h3>
</div>
<div class="modal-body">
<h4>Upload Documents</h4>
<form>
<div class="form-group">
<select data-ng-model="type" class="form-control" id="fileTypeSelect">
<option value="Policy">Policy</option>
<option value="SOP">SOP</option>
</select>
<br>
<div class="input-group"> <span class="input-group-btn">
<input type="file" id="file">
</span>
</div>
<br>
<button type="button" class="btn btn-default" data-ng-click="uploadAttachment($index, type)">Upload</button>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
</div>
And finally my function which resides inside RiskListCtrl (the only controller i use):
$scope.uploadAttachment = function executeUploadAttachment(index, type) {
var listname = "Risk Register";
var id = $scope.items[index].Id;
console.log(indexID);
readFile("uploadControlId").done(function(buffer, fileName) {
uploadAttachment(type, id, listname, fileName, buffer).done(function() {
alert("success");
}).fail(function() {
alert("error in uploading attachment");
})
}).fail(function(err) {
alert("error in reading file content");
});
}
It seems that $scope.items[index].Id is empty. Error: Cannot read property 'Id' of undefined
The modal window has its own scope. That means you need to resolve data you want to pass into the modal's scope. To do so, use resolve within the modals open(options) method.
Before I will give you an example, I want to suggest having only one modal for all your table items. This will let you keep a single template where you can easily use id (now, you create a template for each of your table items which is not valid). Just call a controller function and pass your $index:
<button type="button" class="btn btn-primary uploadBtn" data-ng-show="editMode" ng-click="openModal($index)">Upload file <i class="fa fa-cloud-upload"></i></button>
In your controller, create the modal instance and refer to the template:
$scope.openModal = function(index) {
var modalInstance = $modal.open({
templateUrl: 'myPath/myTemplate.html',
controller: 'MyModalCtrl',
resolve: {
index: function() {
return index;
}
}
});
};
Now you can access index in your MyModalCtrl's scope by injecting index:
angular.module('myModule', []).controller('MyModalCtrl', function($scope, index) {
$scope.index = index;
});
Since, you are getting the index value outside model then you can also use ng-click and then call a function in your controller and store the index value in a temporary variable and then when you are using submit button then just take make another variable and assign the value of temporary variable to your variable. for example:
<button type="button" data-ng-show="editMode" data-ng-click="editMode = false; updateItem($index)" class="btn btn-default">Save</button>
and then make a function in your controller
$scope.updateItem = functon(index)
{
$scope.tempVar = index;
}
now use the value of tempVar in you function
$scope.uploadAttachment = function executeUploadAttachment(index, type) {
var index = tempVar; //assign the value of tempvar to index
var listname = "Risk Register";
var id = $scope.items[index].Id;
console.log(indexID);
readFile("uploadControlId").done(function(buffer, fileName) {
uploadAttachment(type, id, listname, fileName, buffer).done(function() {
alert("success");
}).fail(function() {
alert("error in uploading attachment");
})
}).fail(function(err) {
alert("error in reading file content");
});
}
Here is a code snipped of view and controller. Here what I want just click on save button I mean
<input class="btn btn-primary btn-lg mr-r15" type="button"
ng-click="$parent.saveReleaseNotes(latestReleaseNotes,isEditabel);$apply()"
ng-disabled="formSubmitted" value="{{saveButton}}" />
A request will be sent to server and when get success then tag must be hidden and tag will show but not working
HTML:
<div class="clearfix mr-b25 bdr-b">
<h6 class="mr-tb20">Release Notes
<a ng-if="isEditabel == false" href="" ng-click="$parent.isEditabel = true"
class="f-14 semi-bold mr-l15"> Edit </a>
</h6>
</div>
<p ng-show="!isEditabel" class="form-control-static f-14">{{latestReleaseNotes}}</p>
<div ng-show="isEditabel">
<textarea ng-model="latestReleaseNotes" rows="3" columns="15"
class="form-control" ng-disabled="formSubmitting"></textarea>
<br /> <input class="btn btn-primary btn-lg mr-r15" type="button"
ng-click="$parent.saveReleaseNotes(latestReleaseNotes,isEditabel);$apply()"
ng-disabled="formSubmitted" value="{{saveButton}}" /> <input
type="button" ng-click="isEditabel = false" id="backLink"
class="btn btn-link btn-lg" value="Cancel">
</div>
In controller:
$scope.saveReleaseNotes = function(latestReleaseNotes,isEditabel) {
$scope.backgroundWorking = true;
$scope.saveButton = 'Updating...';
$http({
url: '/apps/'+$scope.app.id+'.json',
method: "PUT",
data: {
releaseNotes: latestReleaseNotes,
appBuildId:$scope.app.latestBuild.id
},
headers: {
'Content-Type': 'application/json'
}
}).success(function(data, status, headers, config) {
if (data.result == "success") {
flash.showSuccess(data.message);
$scope.isEditabel = false;
} else {
flash.showError(data.message);
$scope.latestReleaseNotes = $scope.app.latestBuild.releaseNotes;
}
$scope.backgroundWorking = false;
$scope.saveButton = 'Save';
}).error(function(data, status, headers, config) {
flash.showError("Error occued while updating release notes");
$scope.backgroundWorking = false;
$scope.saveButton = 'Save';
});
}
but model isEditable is not updated in view. I need hide <div> tag and show <p> tag on success.I'm trying by $scope.isEditabel = false; but it is not working.
I think your issue is you are toggling between using $parent.isEditable and isEditable. My first suggestion is to be consistent. Idealy isEditable is contained within the scope that you are using it. It seems a little odd to always be referencing "isEditable" of a parent.
If isEditable truly is contained within the parent you need to be careful about setting $scope.isEditable = true. You can end up redeclaring it on the child scope. I always suggest using functions like setIsEditable(true) and define that in the parent scope.
Trying to create a fiddle for you based on what you have given us.. but I think the below code would work.
//Parent scope
$scope.isEditabel = false;
$scope.setIsEditabel = function(value){
$scope.isEditabel = value;
}
<!-- updated html -->
<div class="clearfix mr-b25 bdr-b">
<h6 class="mr-tb20">Release Notes
<a ng-if="$parent.isEditabel == false" href="" ng-click="$parent.setIsEditabel(true)"
class="f-14 semi-bold mr-l15"> Edit </a>
</h6>
</div>
<p ng-show="!$parent.isEditabel" class="form-control-static f-14">{{latestReleaseNotes}}
</p>
<div ng-show="$parent.isEditabel">
<textarea ng-model="latestReleaseNotes" rows="3" columns="15"
class="form-control" ng-disabled="formSubmitting">
</textarea>
<br />
<input class="btn btn-primary btn-lg mr-r15" type="button"
ng-click="$parent.saveReleaseNotes(latestReleaseNotes,$parent.isEditabel);$apply()"
ng-disabled="formSubmitted" value="{{saveButton}}" /> <input
type="button" ng-click="$parent.isEditabel = false" id="backLink"
class="btn btn-link btn-lg" value="Cancel"/>
</div>
the better solution(always debatable)*:
I created a myModel this isn't necessary but it does clean things up a bit, esp. if you ever have to have multiple editable things on the same page.
We dont have to worry about passing around isEditable to the save, we shouldn't have to worry about apply. General suggestion is to make your html dumber..
//child scope
$scope.myModel = {
latestReleaseNotes: latestReleaseNotes,
isEditabel: false
}
$scope.saveReleaseNotes = function(){
//do save
//we have everything we need on $scope (myModel, isEdiabel, etc.)
}
<!-- updated html -->
<div class="clearfix mr-b25 bdr-b">
<h6 class="mr-tb20">Release Notes
<a ng-if="myModel.isEditabel == false" href="" ng-click="myModel.isEditabel = true"
class="f-14 semi-bold mr-l15"> Edit </a>
</h6>
</div>
<p ng-show="!myModel.isEditabel" class="form-control-static f-14">{{myModel.latestReleaseNotes}}
</p>
<div ng-show="myModel.isEditabel">
<textarea ng-model="myModel.latestReleaseNotes" rows="3" columns="15"
class="form-control" ng-disabled="formSubmitting">
</textarea>
<br />
<input class="btn btn-primary btn-lg mr-r15" type="button"
ng-click="saveReleaseNotes(myModel);"
ng-disabled="formSubmitted" value="{{saveButton}}" /> <input
type="button" ng-click="myModel.isEditabel = false" id="backLink"
class="btn btn-link btn-lg" value="Cancel"/>
</div>