I currently have the following grid on my page:
<tr ng-repeat="cartItem in vm.shoppingCart">
<td>{{cartItem.Title}}</td>
<td>
#using (Html.BeginForm("Delete", "MyController", FormMethod.Post))
{
#Html.AntiForgeryToken()
<input type="submit" value="Delete" id="DeleteBtn" name="DeleteBtn" class="btn blue" />
}
</td>
Our users have requested that the delete happen with a post to the server, so we setup a form in the grid, i'm not sure if that's the best way to go about it. also how would we pass in the Id (cartItem.Id) of the item to delete to the action? Is it common to have a form in each row like this? otherwise we can convince the users to do it through client side.
Related
I'm developing an app for production planning in a factory using appengine/jinja2 and am stuck with how to ask the user to confirm if the app should overwrite existing data or delete an entity in the NDB.
Maybe someone can suggest a course of action?
In product_edit.py I do the following (simplified):
RequestHandler
...
execute query and find given product
template_values = {
'prod_id': query.prod_id,
'prod_desc': query.prod_desc,
}
template = JINJA_ENVIRONMENT.get_template('/html/product_edit.html')
self.response.write(template.render(template_values))
The product_edit.html file looks like below (I'm using w3.css).
...
<form class="w3-container" action="/products-save" method="post">
<label class="w3-text-blue"><b>Product ID</b></label>
<input value="{{prod_id}}" name="prod_id_txt" size="15" class="w3-input w3-border">
<br>
<label class="w3-text-blue"><b>Product Description</b></label>
<input value="{{prod_desc}}" name="prod_(I'm using w3.css)desc_txt" size="50"
<input class="w3-btn w3-blue" type="submit" value="Save">
</form>
It populates two inputs with the product ID and description coming from the NDB and provides a "Save" button.
The save invokes the appropriate request handler to write to the NDB. So I can overwrite the existing NDB entity, no probs.
But how can I ask the user to confirm before overwriting (or deleting) existing data?
In the product-save request handler I can of course display a page asking the user to confirm, but in doing this I lose the data from the original POST.
One option would be to send the data to the new Jinja2 template via hidden fields, and upon user confirmation save the data from the hidden fields. However, this would not win a code beuty contest and is prone to coding errors. Is there anything more elegant I could do?
For the delete form I could do something with a pop-up to ask for confirmation, but I would like to use the same method as for the edit so that they are visually similar.
Thanks in advance!
There are many ways to accomplish this. The most straightforward way is to wire the form submit through a javascript function before submitting. Change:
<input class="w3-btn w3-blue" type="submit" value="Save">
to
<div id="saveWithConfirm">
<input class="w3-btn w3-blue" type="button" value="Save" onclick="confirmOverwrite('ask');" />
</div>
then:
function confirmOverwrite(confirm) {
confirmDiv = document.getElementById("saveWithConfirm");
if ( confirm == "confirmed" ) {
document.getElementById("ID-of-Form-Here").submit();
} else if ( confirm == "ask" ) {
//... if you need to check the database first, do an ajax call here...
confirmDiv.innerHTML = '<input class="w3-btn w3-blue" type="button" value="No" onclick="confirmOverwrite(\'no\');" /><input class="w3-btn w3-blue" type="button" value="Yes" onclick="confirmOverwrite(\'confirmed\');" /> ';
} else {
confirmDiv.innerHTML = '<input class="w3-btn w3-blue" type="button" value="Save" onclick="confirmOverwrite(\'ask\');" /> ';
}
}
This way, you never leave the form.
I have a query regarding angularjs, i.e. I have a table in which I have rows, but these rows are dynamically inserted by user. That means If I have a company having more than one owners then I allow them to add as many owners as they want by simply clicking on add button which is placed with the textboxes (i.e. name, email, number textboxes)
I have used 'ng-repeat' on a row so that the list of owners can be dynamically added one by one. While fetching values from the database it is working perfectly fine but when I am trying to add values by clicking 'add' button, It adds the new row with all the text boxes BUT WITH THE SAME VALUES as the previous row. I think it is because I have used ng-model to link the data.. but then that is the only option I can bind the data.. Do anyone have solution for this problem.? Please help me.
Thank you in advance
I am sharing the code sample for better understanding,
JSP code:
<tbody id="insertionRow">
<tr>
<th>#</th>
<th class="required">Name</th>
<th>Email</th>
<th>Phone No</th>
<th>Add</th>
<th>Delete</th>
</tr>
<tr data-ng-repeat="c in ctrl.client.clientOwnerVOList">
<td>{{$index + 1}}</td>
<td class="col-lg-3"><input type="Text"
class="form-control"
data-ng-model="c.clientOwnerName"
name="clientOwnerName{{$index + 1}}" id="Name">
</td>
<td class="col-lg-4"><input type="Email"
class="form-control"
data-ng-model="c.clientOwnerEmail"
name="clientOwnerEmail{{$index + 1}}" id="Email"></td>
<td class="col-lg-3"><input type="Text"
class="form-control"
data-ng-model="c.clientOwnerPhone"
name="clientOwnerPhone{{$index + 1}}" id="PhoneNo"></td>
<td>
<button type="button"
data-ng-click="insert();"
class="btn btn-sm btn-default">
<i class="fa fa-plus fa-lg"></i>
</button></td>
<td><button type="button"
onClick="$(this).closest('tr').remove();"
class="btn btn-sm btn-default">
<i class="fa fa-trash fa-lg "></i>
</button></td>
</tr>
</tbody>
AngularJS controller code:
$scope.insert = function(){
var tableRow ="<tr data-ng-repeat='c in ctrl.client.clientOwnerVOList'>"+
"<td>"+i+"</td>"+
"<td class='col-lg-3'><input type='Text' class='form-control' data-ng-model='c.clientOwnerName' name='clientOwnerName{{$index + 1}}' ></td>"+
"<td class='col-lg-4'><input type='Email' class='form-control' data-ng-model='c.clientOwnerEmail' name='clientOwnerEmail{{$index + 1}}'</td>"+
"<td class='col-lg-3'><input type='Text' class='form-control' data-ng-model='c.clientOwnerPhone' name='clientOwnerPhone{{$index + 1}}' ></td>"+
"<td><button type='button' data-ng-click='insert()' class='btn btn-sm btn-default'><i class='fa fa-plus fa-lg'></i></button></td>"+
"<td><button type='button' class='btn btn-sm btn-default' onClick=$(this).closest('tr').remove();><i class='fa fa-trash fa-lg '></i></button></td>"+
"</tr>";
var compiledString = $compile(tableRow)($scope);
$("#insertionRow").append(compiledString);
i++;
};
And the client Object is as follows
self.client= {
clientID:'',
clientName:'',
clientDescription:'',
clientAddressLine:'',
clientContactPersonPhone:'',
createdOn:'',
astUpdatedOn:'',
country:'',
state:'',
city:'',
isDeleted:'',
clientOwnerVOList: [
{
clientOwnerID:'',
createdOn:'',
isDeleted:'' ,
clientOwnerName:'',
clientOwnerPhone:'',
clientOwnerEmail:''
}
]
}
I tried to reproduce your problem in this plunker :
https://plnkr.co/edit/Eqw21bGNetGtHZIQZCYw?p=preview
I changed your insert function to create new clientOwnerVO.
I just push new object like this :
$scope.client.clientOwnerVOList.push({clientOwnerID:'',
createdOn:'',
isDeleted:'' ,
clientOwnerName:''
,clientOwnerPhone:''
,clientOwnerEmail:'',});
i++;
I hope i understand your problem
The insert function is pretty strange. AFAIT you are inserting some compiled HTML into the DOM. Angular's whole thing is for you to avoid doing this by hand. You should be changing ctrl.client.clientOwnerVOList directly by appending the required JS objects to it and then the change will be reflected by the DOM.
The code should look similar to this, plus-minus application specific logic which you know better.
$scope.append = function() {
self.client.clientOwnerVOList.push({
clientOwnerId: 'newid',
createdOn: 'today',
isDeleted: 'false',
clientOwnerName: 'foo',
clientOwnerPhone: 'bar',
clientOwnerEmail: 'foo#bar.com'
});
}
The values to populate the client info would be taken from other places (other models fields, or some sensible defaults etc.)
Basically, you have a bunch of data (self.client, and any other controller variables from the scope). The view is a function of this data, and you describe how to build the DOM through the html template which can access the fields from the scope. It's Angular's job to figure out how to do that. Whenever some sort of event happens, like a button press or network event etc., you update the data, and then Angular rebuild the DOM for you.
<tr ng-if="usernames.length" ng-repeat="user in usernames">
<td><input type="radio" name="radio" ng-model="form.currentPatient" value="{{user}}" id="{{user.id}}"></td>
<td>{{user.firstname}} </td>
<td>{{user.lastname}}</td>
<td>{{user.address}}</td>
<td>{{user.age}}</td>
</tr>
</table>
<div>{{form.currentPatient}}</div>
<button type="submit" value="View Profile" onclick="location.href('result.html' )">View Profile</button>
If I click on that radio button ,the corresponding json values should be redirect to the result page
Please help me ......
If not using routeprovider
You can create shared service or factory to store value and retrive in other pages.
If using routeprovider
You can bind JSON value in URl this way-:
window.location="#/result/firstname="+$scope.user.firstname+"&&lastname="+$scope.user.lastname+"&&age="+$scope.user.age; And You can access this value as $location.search()['firstname'], $location.search()['lastname'], $location.search()['age']
you can access this value as-:
$location.search()['firstname'] for firstname,
$location.search()['lastname'] for lastname and
$location.search()['age'] for age
you can add $location in function like as $scope .
I am doing a simple form using angularjs with angular-ui. Somehow angular is inserting boostrap tooltips into my validation. But it is getting inserted automatically and I do not know how to control/customize or disable the tooltips. Here is my html:
<form name="frm" ng-submit="contact.contactUsSubmit(frm)">
<table id="tblContactUs">
<tr>
<td id="tblContactUsTitleTd">
Send us an email
</td>
</tr>
<tr>
<td>
<span class="LabelStyle1">Name:</span><br/>
<input type="text" tooltip-trigger="0" name="name" style="width: 75%" ng-model="contact.formInfo.name" required/><br/>
<span ng-show="frm.name.$dirty && frm.name.$error.required" class="errorMsg">Required!<br /></span>
<span class="LabelStyle1">Email:</span> <br/>
<input type="email" name="email" style="width: 75%" ng-model="contact.formInfo.email" required/><br/>
<span ng-show="frm.email.$dirty && frm.email.$error.required" class="errorMsg">Required!<br /></span>
<span ng-show="frm.email.$dirty && frm.email.$error.email" class="errorMsg">Not a valid email!<br /></span>
<span class="LabelStyle1">Message:</span> <br/>
<textarea name="message" rows="5" style="width: 100%" ng-model="contact.formInfo.message" required></textarea><br/>
<span ng-show="frm.email.$dirty && frm.name.$error.required" class="errorMsg">Required!</span>
</td>
</tr>
<tr>
<td style="text-align: right">
<button>Submit</button>
</td>
</tr>
</table>
</form>
:
But I am getting this:
Yes the tooltip is nice. But I didn't say I wanted it there. IF I want to use the tooltip for validation, I need to be able to customize the message (for different languages). I have googled the bejesus out the topic but I can't find answers as to how to configure it or to turn it off. I don't even know why its there in the first place. Any help would be much appreciated.
Those aren't bootstrap or even css related in any way.
They are html5 validation tooltips that are part of the browser itself.
If you don't want to use built in browser validation add the novalidate attribute to <form> tag.
<form name="frm" ng-submit="contact.contactUsSubmit(frm)" novalidate>
Reference MDN <form> docs
Thank you to charlietfl for putting me on the right track with "novalidate." The problem with novalidate, however, is that when you hit ng-submit none of the validation error messages showed up.
The complete solution was to add the following code to the form tag ("contact" an alias for "contactController":
<form name="frm" ng-submit="contact.formIsValid(frm) && contact.contactUsSubmit(frm)" novalidate>
In the controller the two functions went as follows:
formIsValid(frm) {
angular.forEach(frm.$error.required, function (field) {
field.$setDirty();
});
return frm.$valid;
}
contactUsSubmit(frm) {
var scope = this;
if (frm.$valid) {
//do $http post data etc here
}
return frm.$valid;
}
Now, if when someone hits submit, the field are made "dirty" and this causes the angular validation rules to fire. If the form is valid then the submit goes thru, if not then we are left with the validation errors.
Why does Angular not allow duplicate data to be submitted? I am using ng-list to write all points scored using a simple controller.
For example - If a player inputs '10' into my app and then another player also does the same the ng-submit will stop functioning completely. I haven't specified anything else to allow this to happen. How can I change this default behaviour so users are allowed to post duplicate values?
Controller:
bowlingApp.controller('bowlPoints', function ($scope){
$scope.bowlPoints = [];
$scope.addBowlPoints = function() {
$scope.bowlPoints.push($scope.enteredPoints);
};
});
HTML
<form ng-submit="addBowlPoints()" role="form">
<div class="form-group">
<label>Player Score</label>
<input type="text" class="form-control" ng-model="enteredPoints">
</div>
<button type="submit" class="btn btn-default">Submit</button>
</form>
<tr>
<ul>
<td>Player </td>
<td ng-repeat="points in bowlPoints ">{{points}}</td>
</ul>
</tr>
ng-submit works fine, in your example it adds value to array bowlPoints, but you just can not to see it.
To see an array and that ng-submit works fine you can type {{bowlPoints}} in your HTML file.
But if you want to see all data in table and if you want your table will to update and angular dynamically add your columns - you need to add track by in your ng-repeat
<td ng-repeat="points in bowlPoints track by $index ">{{points}}</td>
Demo: http://plnkr.co/edit/oFMm9Jqk034IRvS1qOCO?p=preview
I believe submit only does something if the form is dirty. Since the first submit will have cleared the dirty state, it won't do anything. You could try manually setting the dirty state of the form. Failing that, you could use ng-click instead and do the form submission yourself.