Access an angular page from a form - angularjs

I would like to access an angular page from an html form. But when I submit the form via method get and with parameter I get some problem with the url.
Here is a simple form to reproduce the problem :
<form action="http://ncel28182/pl/Angular/#/FFCO">
<input type="text" name="test">
<button>toto</button>
</form>
When I click on the submit button, it open a page where the url is
http://ncel28182/pl/Angular/?test=#/FFCO
It seems that the parameters are placed before the #.
Is there a way to fix it ?

I believe you should use $location to change location, and a service to share data, as in the following :
HTML :
<form name="myForm" ng-submit="submit()">
<input type="text" name="test">
<button>toto</button>
</form>
Javascript :
function submit($scope, $location, MyService) {
MyService.data = $scope.myForm.test;
$location.url("/pl/Angular/#/FFCO");
}
In the other's page controller, define the service as a dependency and you will be able to access the up-to-date data.
Please note that I'm not a professional angularjs user or even a webdevelopper, you should probably wait for other users to react to my answer or add their own.

Since you can't edit the form sending data, you can't use ngRoute to directly route to the desired "FFCO" view because ngRoute matches against $location.path, whereas the form sends the "FFCO" part as the $location.hash. Since you have no $location.path provided, the form will target your application root.
What you will want to do is add some js code in this page to handle the location change :
if ($location.hash() === "/FFCO") { $location.path("/FFCO"); }
This should do the trick, translating the url requested by the form to a format understandable by your angularjs application. I don't think this will change the hash, if an extra #/FFCO by the end of your URL is a problem you should remove it with $location.hash('').
I believe the best place to do so would be in an extra controller added somewhere after your app bootstrap code.
This is obviously still sub-optimal, I wish I had a better solution.

Related

How to find and replace a specific text on a page

How to find and replace a specific text on a html page using AngularJs
That text is on a third party component so the id and the class is keeping changing. What I can reference is the text itself that I want to change.
That specific text on the html page is no class or id or any ng-tag around it.
I am not a angularjs developer and the page was built on asp.net mvc with the view (cshtml) using angularjs version1.
Is there a way in angularjs to find and place the text like the way in javascript:
document.body.innerHTML = document.body.innerHTML.replace('old_text', 'new_text');
Thank you!
In angularjs each application state(page) has a controller. The logic to access the Dom should placed in said controller.
To manipulate the DOM please see this answer
In Angular world, it's called data binding. Here are the official docs on data binding.
Here is the working DEMO of data being updated in time. First, html displays "Initial Text" and in 5 seconds it's changed to "New Text".
What was done for this demo:
An angular component was created with a dedicated variable $scope.text that holds text values that will change in time.
Then, this variable is used in the HTML markup, like this: {{ text }}.
Angular handles the HTML re-rendering automatically for you, so when the value of $scope.text is modified in the component, Angular forces re-rendering of the html in the browser
UPD another example with Angular two-way binding: DEMO.
Here user can change $scope.text value in the input field, which automatically changes its value in the controller. Try to edit the input field and you will see how it instantly updates in the header above the input field.

HTML not rendering on Salesforce using $sce and ng-bind-html

I am using Salesforce as the back end and my users can get some notifications that could contain an tag with a link to somewhere. This being said I have used $sce in the controller to do a function like this:
vm.to_trusted = to_trusted;
function to_trusted(html_code) {
return $sce.trustAsHtml(html_code);
}
In the front end I am using it as such:
<p ng-bind-html="vm.to_trusted(message.body)"></p>
An example of the returned message.body is
Click Here to Fill out your Profile. It will allow you
On localhost this works awesome with the link being shown and not the tag. On Salesforce, this is not the case with the above being shown instead. Any ideas as to why this is not working?
UPDATE:
Yes I do have ngSanitize included :)
The Salesforce #dispatch requests serialize text in an odd manner.
If the content of a Salesforce string is: 'Things' you will see in Angular that you've received: <a href="$quot;>Things<a>
The solution I've found is, in your controller:
function to_trusted(html_code) {
// Cause the &ltg; etc become '<'
return $('<textarea />').html(html_code).text();
}
Because Salesforce.

ngForm not work in web application, but does in jsFiddle

I am trying to use the $invalid properties of ngForm to disable a submit button in my app. For some reason, the FormController instance that I should have access to after the <form> is created is not available. However, I moved the code over to jsFiddle and for some reason it works now.
Here is the jsFiddle
In my real application, there are no errors in the console and I am including angular.min.js correctly because everything else works fine. I am lost on what to try next since the code is basically the same in both.
Without seeing what is in your controller this is just a guess, but when I have problems with things not working for obscure reasons I generally am able to solve the problem by creating an object in scope and hanging everything off of it (much like you have already done.)
function Controller($scope) {
$scope.form = {
email:'',
employees:'',
migDate:''
};
}
The trick here is that you need to name your form similarly:
<form name="form.newMigForm" novalidate ng-controller="myControllerName">
and then when you check $invalid in your button, you use the same convention:
<input id="qaStartForm" ng-disabled="form.newMigForm.$invalid" ng-click="submitNewMigration()" type="button" class="btnOrangeLarge" value="Start" />
This problem generally arises when you use the UI Modal and they tell you to access it like this in the docs. I have used it successfully in other areas and solved the mystery that was plaguing me.

Submit form: Assert that the DOM is completely rendered

I’d like to submit a form but add some hidden inputs first. The hidden inputs are added with a ng-repeat. Eventually they will be rendered, but how can I be sure that the DOM is already updated prior to triggering the submit event?
partial:
<form ng-submit="addValuesAndSubmit()">
<input type="hidden" name="{{name}}" value="{{value}}" ng-repeat="(name, value) in order">
<input type="submit">
</form>
controller:
$scope.addValuesAndSubmit = function() {
$scope.order = { param1: 1, param2: 2 };
// TODO: wait until form is rendered
// there should be two <input type="hidden"> now
// trigger submit action
};
As I understand it, a post-linking function for a directive could be used for this. Am I right or am I missing something obvious?
EDIT: The form data needs to be posted to an external website, redirecting the browser to the response. It’s a payment integration where I calculate an HMAC on the server, add it to the form as a hidden element and then post it to the payment provider. The implementation of $http.post() seems not to do that redirect but returns the response instead.
With Angular apps, you often want to submit your model, rather than extract your data from form elements. I.e., use ng-model to specify $scope model object properties, then submit that model object via ng-submit. It would seem to me that you already have access to order in your $scope, since you are trying to get your associated view to use it. So you probably don't need to wait for the view to update -- just use order directly in your addValuesAndSubmit() function.

AngularJS : What's the Angular way to interact with a form?

I understand one of the key principals of Angular is:
Thou shalt not reference thy DOM from withinst thou's controllers.
I'm trying to process a credit card payment, which requires the following steps:
User fills out a form, and clicks a submit button
A portion of that form is sent to our servers, which starts a transaction with the payment gateway
The response from our servers updates values in the form, which must then be submitted directly to the payment gateway, via a form POST.
Other stuff happens.
In this scenario, how do I:
Update the data in the form (without referencing the form from the controller)
Get the form to submit?
The form binds to a model on my controller, so I've tried something like the following:
<form action="{{paymentModel.urlFromTheResponse}}">
<input type="hidden" name="accessCode" value="{{paymentModelaccessCodeFromResponse}}" />
<button ng-click="startTransaction(paymentModel)"></button>
</form>
// in my success handler
.success(function(data) {
paymentModel.urlFromTheResponse = data.url;
paymentModel.accessCode = data.accessCode;
$scope.apply();
}
the theory being here that if I can immediately get the form into the correct state via databinding, I can then do something to submit the form. However, this throws an error:
Digest already in progress
What's the Angular way to support this type of flow? It seems I'm required to interact directly with the DOM, which goes against the nature of controllers.
As others have stated, you shouldn't need to call $scope.$apply() because the form should already be tied to angular by setting ng-model attributes on each of the fields.
However, occasionally it is necessary to call $scope.$apply() to update display when data is pulled in from some other source outside of angular...
In those cases, I've had great luck with this:
// This method will be inherited by all other controllers
// It should be used any time that $scope.$apply() would
// otherwise be used.
$scope.safeApply = function(fn) {
var phase = this.$root.$$phase;
if(phase == '$apply' || phase == '$digest') {
if(fn && (typeof(fn) === 'function')) {
fn();
}
} else {
this.$apply(fn);
}
};
I place that in my outermost controller, so all other controllers on the page inherit the function from it.. Any time I find I need a call to apply, I instead call $scope.safeApply() which will call apply if there is not already an apply or digest in progress, otherwise, those changes will already be picked up by the currently running apply/digest.
In your code I would change this:
<input type="hidden" name="accessCode" value="{{paymentModelaccessCodeFromResponse}}" />
To this:
<input type="hidden" name="accessCode" ng-model="paymentModel.accessCode" />
I would probably also remove the form action, and instead add something like this in the controller:
$scope.$watch('paymentModel.accessCode', function() {
// Fire off additional form submission here.
})
The error is generated because your success callback is already "inside Angular", so $scope.apply() will be called automatically for you.
If you use ng-model (instead of value) on your form elements, then you can modify the model/$scope properties in your success callback and the form will automatically update (due to two-way databinding via ng-model). However, instead of trying to submit the form, why not just use the $http or $resource service inside your controller to call the web service? (That's why I asked if the user needed to be involved in my comment.)
Assuming you are using something like $http, you are already inside of the angular scope and should not need to manually call $scope.apply(); as you are inside of the angular execution already.
You should be able to ditch the $scope.apply() and simply have an
.success(function(data) {
paymentModel.urlFromTheResponse = data.url;
paymentModel.accessCode = data.accessCode;
$http.post("/finalstep",paymentModel).success(function(data)
{
// other stuff
});
}

Resources