Store value of span or textarea in angularjs view - html

I have a call to a controller in my ASP.NET WebForms page:
input type="button" data-ng-click="addReply(post.PostId, LoggedInDisplayName, post.NewReply)" value="Submit" id="createReply" class="btn btn-default pull-right"
LoggedInDisplayName is a variable I need to pass to the addReply method, which does a RESTful API HTTP call in the service.
Unfortunately LoggedInDisplayName is a field that can only be sourced by ASP, as this is the login name of the current user, and I'm using Microsoft's built-in membership profile routines.
I can place the login name into a hidden span or textarea element using this logic in my code-behind C# file:
if (Membership.GetUser() != null)
{
loggedInDisplayName.InnerText = Membership.GetUser().ToString();
}
where loggedInDisplayName is the ID of the span or textarea.
But, how can I get the contents of the span or textarea into the LoggedInDisplayName field? I tried using ng-model, but this doesn't work - the span/textarea is reverted to a blank field.
Any assistance would be much appreciated.

just put in your submit button, ng-init="loggedInDisplayName = (asp variable)". This will initialize the variable to your asp variable.

To solve this problem, I loaded the asp variable into the DOM as follows
span style="visibility:hidden" id="loggedInDisplayName" ><%: LoggedInDisplayName() %>
And in the .cs code behind file:
public string LoggedInDisplayName()
{
string loggedInDisplayName = "";
// set the login name for use in creating new posts and replies
if (Membership.GetUser() != null)
{
loggedInDisplayName = Membership.GetUser().ToString();
}
return loggedInDisplayName;
}
Then a controller to create the variable in the scope
// The Global Variable defined outside angular
var loggedInDisplayName = $('#loggedInDisplayName').text();
//Define Controller
gwApp.controller('LoginName', ['$scope', '$window',
function ($scope, $window) {
$scope.LoggedInDisplayName = $window.loggedInDisplayName;
}
]);
I wrapped my existing controller in the new controller:
div id="loginName" data-ng-controller="LoginName">
... existing code ...
/div>
Then my Submit button:
input type="button" data-ng-click="addReply(post.PostId, LoggedInDisplayName, post.NewReply)" value="Submit" id="createReply{{ post.PostId }}" class="btn btn-default pull-right" />

Related

Thymleaf how to take an input and then redirect to another page

I'm learning Spring boot. I have a list of products with unique ids, and I want to implement a "lookup by id" functionality, but I don't know how to do it, I searched but got totally different stuff.
I already have a #Getmapping method like this:
#Getmapping(/products/{id})
If I manually type in the id in the url I'll get what I what. But I want to have an input box in the HTML page like:
<form>
Look up by id: <input/>
</form>
and after I submit the form it'll redirect to that page. For example, if I enter input of 1, it'll go to localhost:8080/products/1
I've been searching but all I got was stuff about #Postmapping.
Add a #PostMapping to your controller:
#Controller
#RequestMapping("/products")
public class ProductController {
#GetMapping //Controller method for showing the empty form
public String index(Model model) {
model.addAttribute("formData", new SearchFormData()); // Create an empty form data object so Thymeleaf can bind to it
return "index";
}
#PostMapping
public String searchById(SearchFormData formData) {
return "redirect:/products/" + formData.getId(); //Use the value the user entered in the form to do the redirect
}
#GetMapping("/{id}")
public String showProduct(#PathVariable("id") long id) {
...
}
}
With SearchFormData representing the form fields (there is only 1 field in this case):
public class SearchFormData {
private long id;
// getters and setters
And update Thymeleaf template like this:
<form th:action="#{/products}" th:method="post" th:object="${formData}">
<input th:field="*{id}" type="number">
<button type="submit">Search</button>
</form>
Note that the value of th:object needs to match with the name used to add the SearchFormData instance to the model.
See Form handling with Thymeleaf for more info.
The following simple code will direct you to a URL that is generated from a concatenation of the base address of the <form>'s action attribute and the value of its first <input>:
document.querySelector("form").addEventListener("submit",function(ev){
ev.preventDefault();
this.action="/product/"+this.querySelector("input").value;
console.log(this.action);
// in real code: uncomment next line!
// this.submit()
})
<form>
Look up by id: <input type="text" value="123" />
</form>
In the real code you will delete the console.log() und uncomment the following line: this.submit().
Alternatively you could also do:
document.querySelector("form").addEventListener("submit",function(ev){
ev.preventDefault();
location = "/product/"+this.querySelector("input").value;
})
This will redirect you to the page without actually submitting the form.

Angular: Enable button asynchronously

I am fetching data in my angular app from a REST API. I want to enable the button of the search once the user logs in. I have added auth.service.ts which I am importing in my search navbar component. But, the button doesn't get enabled once the user logs in. The data is asynchronous so, it either remains disabled or enabled. I can't figure it out.
Here's my code:
navbar.component.ts
allowSearch: boolean = false;
buttonEnable() // this should get called every time change is detected in the input
{
if(this.authService.isAuthenticated())
{
this.allowSearch = true;
}
}
navbar.component.html
<input type="text" value="" class="form-control" (change) = "buttonEnable()" placeholder="Search..." [(ngModel)] =
"searchElement" name = "searchElement"
style = "background-color: #faf9f9" id = "searchElement" >
<div class="input-group-append" style = "background-color: #faf9f9">
<button type="button" name="button" type = "submit" [disabled] = "!allowSearch" (click) =
"openModal2(); onSearch(searchElement)"><i class="nc-icon nc-zoom-split"></i></button>
</div>
If you call to authService outside of navBar, you can get it if your service has, futhermore a method to login, a Subject. Else simply change the variable in the subscribe function.
e.g. using Subject:
LoginService(){
isLoggin:Subject<boolean>=new Subject<boolean>()
loggin(data){
this.httpClient.get(....).pipe(
tap(res=>{
if (.....)
this.isLoggin.next(true)
})
)
}
loggout(){
this.httpClient.get(....).pipe(
tap(_=>{
this.isLoggin.next(false)
})
)
}
}
Your nav-bar-component inject in constructor the loginService -make it public-
constructor(public loginService:LoginService){}
And your .html can be simple
<button [disabled]="!(loginService.isLoggin|async)">I'm login</button>
(*)tap not change the response, but executed when "someone" subscribe to our observable.
Here 'this.allowSearch' is getting initialized in buttonEnable(). Once you login to the application, You should call the 'buttonEnable()' method.
Same wise, When ever you logout from app, you should invoke the 'buttonEnable()' method.
So 'allowSearch' value will be updated.
Instead of this approach, you should have RXJS observables. have 'allowSearch' property in RXJS store and update based on login and logout actions.
Your component should subscribe for 'allowSearch' from store and update the 'allowSearch' component property.

Disable button after form submit

Sounds easy and a well known question, right? I thought so as well. How do I do this in angularJS.
CSHTML
#using (Html.BeginForm("Order", "Shop", FormMethod.Post, new { #class = "form-horizontal", role = "form" }))
{
<div class="container" ng-app="order" ng-controller="orderController">
<button type="submit" ng-disabled="orderButtonClicked" ng-click="orderClicked()" class="btn btn-primary btn-block tf-btn btn-lg">Place Order</button>
</div>
}
AngularJS
angular.module("order", [])
.controller("orderController", ['$scope', '$http','$filter', function ($scope, $http, $filter) {
$scope.orderButtonClicked = false;
$scope.orderClicked = function () {
$scope.orderButtonClicked = true;
}
}]);
As many others reported as well, the form is not submitting when disabling or removing the button. this answer did the same, he claims it is working, but for me is a no go.
You can assume that angular is setup correctly, disabling the button works fine.
I've never had much luck with disabling the submit button in any circumstances - even if it doesn't prevent the form from submitting, the server can get confused because it expects the name/value combination from the submit button.
Instead, I generally hide the submit button, and replace it with something appropriate:
<button type="submit" ng-show="!orderButtonClicked" ng-click="orderClicked()" class="btn btn-primary btn-block tf-btn btn-lg">Place Order</button>
<button ng-show="orderButtonClicked" disabled class="btn btn-primary btn-block tf-btn btn-lg">Place Order</button>
Keep in mind that even in this case, the user may be able to re-submit by hitting enter in a textbox.
Try this way:
<div ng-app="myApp" ng-controller="myCtrl">
<form>
<input type="submit" ng-disabled="orderButtonClicked" ng-click="orderClicked()">
</form>
</div>
<script>
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope) {
$scope.orderButtonClicked = false;
$scope.orderClicked = function () {
$scope.orderButtonClicked = true;
}
});
</script>
I will put a break point there and see if orderButtonClicked is set to true when orderClicked() is triggered. Just another thought, I have experience with this issue before when I have an ng-if somewhere inside the controller scope in html. This is because angular seems to create a new scope inside that ng-if dom. The best way to avoid that is to use controllerAs and then access the scope property using controllerName.propertyName.
Does the form submit if you don't disable or remove the button? The angular documentation states that, "For this reason, Angular prevents the default action (form submission to the server) unless the <form> element has an action attribute specified."
So, depending on what you're trying to accomplish, you would have to add javascript in your .orderClicked method to make an ajax call, for example, or whatever you're trying to accomplish.

how to pass json response from one html page to another html page using angularJs?

I have api for search functionality which has written in Laravel PHP.When I type some string in input tag and click on search button, then I am geeting the json response.
Now what I have to do is on ngClick a new html page should open say "search.html" with display the json response using angularjs.
I am not able to do, may be my lake of knowledge:). Can anybody tell me how can I do this.
Here is my code:
// Search Controller
QAApp.controller('SearchCtrl', function ($scope, $http) {
$scope.search = function (searchtag) {
var request = $http({
method: 'GET',
url: server + 'api/question/tagged/' + searchtag,
});
request.success(function(data, status, headers, config) {
console.log(data);
$scope.qa = data;
});
}
});
html page is :
<div class="collapse navbar-collapse navbar-ex1-collapse" ng-controller = "SearchCtrl">
<div style = "float: right; margin-top: 7px;" class="col-sm-3 col-md-3">
<form class="navbar-form" role="search">
<div class="input-group">
<input type="text" class="form-control" placeholder="Search...." name = "tag" ng-model = "tag">
<div class="input-group-btn">
<button type="submit" class="btn btn-primary" ng-click = "search(tag);">
<span class="glyphicon glyphicon-search"></span>
</button>
</div>
</div>
</form>
</div>
Over here you have two different pages and whenever you are moving from one page to other (no SPA) the page will complete refresh....so if one is thinking of having it in global variables, services or even $rootScope that will not work as these variables will get refreshed.
In order to cope up then we either need to work with cookies, querystring or the browser localStorage.
In order to use local Storage in Angularjs you need to include a script in both the pages for angular-local-storage Github Link
Code Example how to use it:
angular.module('yourModule', ['LocalStorageModule'])
.controller('yourCtrl', [
'$scope',
'localStorageService',
function($scope, localStorageService) {
// Start fresh
localStorageService.clearAll();
// Set a key
localStorageService.set('Favorite Sport','Ultimate Frisbee');
// Delete a key
localStorageService.delete('Favorite Sport');
}]);
/*
To set the prefix of your localStorage name, you can use the setPrefix method
available on the localStorageServiceProvider
*/
angular.module('yourModule', ['LocalStorageModule'])
.config(['localStorageServiceProvider', function(localStorageServiceProvider){
localStorageServiceProvider.setPrefix('newPrefix');
}]);
Library main functions:
.set : to set a key value in the localStorage space
.clearAll: clear all the keys in localStorage
.delete: delete a key
.get: get a key from localStorage
Working Fiddle
Reference of what local Storage is actually about

Using 2 buttons in same ASP.NET MVC Form

In general, is it possible to have two different buttons within the same form that post to different controller actions in ASP.NET MVC?
I am essentially trying to have two input (type="button") tags in the same form, but I want them to perform different controller actions. I would like to do this in a few cases because I think it provides a good aesthetic to be able to click buttons as opposed to hyperlinks. Is there a way to do this or should I design it differently?
Not really possible without using Javascript. With Javascript you'd just have to define different click handlers that invoked the proper action.
$(function() {
$('#button1').click( function() {
$(form).attr( 'action', '<% Url.Action( "action1" ) %>' )
.submit();
return false; // prevent default submission
});
$('#button2').click( function() {
$(form).attr( 'action', '<% Url.Action( "action2" ) %>' )
.submit();
return false; // prevent default submission
});
});
Some thoughts about handling this in the browser:
You can use links which are styled to look like buttons. This is easy to do, either with images or by putting the link in a block element with borders.
You can use two buttons which don't directly submit; they instead call a javascript function that sets the form action before submitting.
If all you want is something like OK & Cancel buttons, then have a look at this post by David Findley.
I'm using this method on my Edit view, where I have an Edit button and a Delete button. The delete button only requires the Id of the item. In the code below you can see that I've named my attribute "AcceptFormValueAttribute". This is method good for me, because my Delete [Get] action just shows a message asking for confirmation, so needs the redirect.
[ActionName("Edit")]
[AcceptFormValue(Name = "Action", Value = "Delete")]
[AcceptVerbs(HttpVerbs.Post)]
[ValidateAntiForgeryToken]
public ActionResult EditDelete(int? id)
{
return RedirectToAction("Delete", new { id = id });
}
This has nothing to do with ASP.NET MVC but with html. The only way I see how you could do this is by modifying the action attribute of the form tag using javascript on submission of the form by checking which button was pressed.
Well there are a few ways you could handle this. Assuming you aren't sending data with the button click I'd go with option 3. If data must be included then consider option 1 with some sort of temporary data store (like TempData).
One form posts to one controller
action on submit and the controller
action checks which button was
clicked and then dispatches a
RedirectToAction(). (Not great)
Multiple forms on one page post to multiple controller actions (Better)
Inside or outside a form create an input type="button" and give it an onclick handler
that redirects the user to a controller action (Best)
Haven't tried this, but given the ID of the clicked button does get sent VIA http POST, you could probably do something like:
<input type="submit" name="GO" ID="GO" value="GO BUTTON" />
<input type="submit" name="STOP" ID="STOP" value="STOP BUTTON" />
Then on the mvc end, just have two methods, one with a go parameter, one with a stop parameter.
Method #1
How about using two different forms wrapping the buttons, then using CSS to position one of them so that it appears (visually) to be inside the "main" form?
A really quick example:
<fieldset id="CombinedForm">
<form ... action="Method1">
...form stuff here...
<input id="Button1" type="submit" value="Do something">
</form>
<form ... action="Method2">
...form stuff here...
<input id="Button2" type="submit" value="Do something else">
</form>
</fieldset>
...Then using CSS as follows:
#CombinedForm {
position: relative;
padding-bottom: 2em; /* leave space for buttons */
}
#Button1, #Button2 {
position: absolute;
bottom: 0;
}
#Button1 {
left: 0;
}
#Button2 {
right: 0;
}
The result should be that you have a fieldset or div which looks like a form, having two actual HTML forms inside it, and two buttons which are positioned within the parent box, yet submitting to different locations.
Method #2
Another method occurs: have both buttons in the same form, pointing to one controller action, that then decides (based on the value of the button clicked) which action to redirect to.
Its not Javascript required...
how about this
public ActionResult DoSomething()
{
// Some business logic
TempData["PostedFormValues"] = Request.Form;
if (Request.Form("ButtonA") != null)
{
return RedirectToAction("ActionA", RouteData.Values);
}
return RedirectToAction("ActionB", RouteData.Values);
}
I think that I can suggest more simple one.
For example you have two buttons : ButtonA,ButtonB and want to perform different
action on each one.
Simplest solution is : just use BeginForm statement:
#using ( Html.BeginForm("ButtonA" , "Home") )
{
<input type="submit" value="ButtonA"/>
}
#using ( Html.BeginForm("ButtonB" , "Home") )
{
<input type="submit" value="ButtonB" />
}
You must also declare ButtonA,ButtonB actions in your Home controller :
[HttpPost]
public ActionResult ButtonA()
{ . . . }
[HttpPost]
public ActionResult ButtonB()
{ . . . }