Get values from link that brought my to the current page - javascript

I know - the first thing you're gonna say is "Use the referrer!"
But that'd be the wrong answer, and I'll explain why.
Assume you're on a page, say "Employees", that has a search. The search fields for name yield a table of employees upon submitting. In that table, the Employee Name is a clickable object, in this case a hyperlink. That link goes to an Employee Details page. On that page, there isn't really anything, because that page actually loads up a bunch of Angular data from a subpage.
So, the problem:
On Employees, you click on a link:
http://localhost/EmployeeData#/details/cc30e1f8-b21c-4384-9710-e927686c925c
That link takes you to the EmployeeData controller and index view. The index view loads up details.html, which is an angular happiness full of data. It works great.
But back in the Index view, there's a tiny bit of code that tells the details where to show up, and has a breadcrumb. So in the Index ViewResult, (EmployeeData/Index.aspx), I'd like to be able to pull the GUID from the link that got you there... But when I use the referrer, it just tells me "You came from the Employee Search".
public ViewResult Index()
{
var vm = _vmp.GetViewModel<EmployeeDataViewModel>();
vm.Breadcrumb = CreateBreadCrumbDisplay();
return View(vm);
}
public string CreateBreadCrumbDisplay()
{
var referrer = (Request.UrlReferrer != null) ? Request.UrlReferrer.AbsoluteUri : string.Empty;
var curUrl = Request.ServerVariables["SCRIPT_NAME"];
//do lots of stuff
return theBreadCrumb;
}
In this instance, CreateBreadCrumbDisplay just returns http://localhost/Employee. And curUrl just has "EmployeeData", thanks to all the real data stuff happening in the angular page, and not actually in the Index view.
So, what I need to do is grab the full URL, with the ID, and pass that ID into my "CreateBreadCrumbDisplay" method.
Thoughts?

I think a possible solution would be to grab the URL params with $routeParams and pass it to your CreateBreadCrumbDisplay method from Angular.
If I understand your problem correctly reading up on $routeParams here should solve your problem.
Here is an example of how it should work:
First config your routes in Angular
myApp.config(function($routeProvider) {
$routeProvider.when('/link/:GUID', {
controller: 'SomeCtrl',
templateUrl: 'sometemplate.html'
});
});
Then in your controller
myApp.controller('SomeCtrl', function($scope, $routeParams) {
console.log($routeParams);
});
Link to it from somewhere
foo
And finally the console output:
{ GUID: "cc30e1f8-b21c-4384-9710-e927686c925c" }

As long as I understand , you can use $location service , $location.absUrl(); And you may succeed this in many other ways even passing your url to action method as a parameter while submitting .

Related

How to pass query string data or any value from url to controller function in AngularJS?

Suppose I have few links in page and each link has date like:
**https://mysite/blogs/01/01/2017
https://mysite/blogs/02/01/2017
https://mysite/blogs/03/01/2017
https://mysite/blogs/04/01/2017**
How can I capture date and fetch data date wise when doing Angular routing ?
I am new so like to know how people pass query string data or any value from url to controller function with example code.
**https://mysite/blogs?custid=101&orderid=200
https://mysite/blogs/{customerid}/orders
https://mysite/blogs/{customerid}/{orderid}**
Please post a small sample code having controller, view and routing code if possible.
I am very eager to see how to handle query string or rest based URL kind with Angular routing which will pass data to controller and controller fetch data accordingly.
$routeProvider.when('/blogs/:day/:month/:year', {
templateUrl: 'blog.html',
controller: 'BlogCtrl'
});
Then in your controller, inject $routeParams to get the params:
function BlogCtrl($scope, $routeParams) {
$scope.day = $routeParams.day;
$scope.month = $routeParams.month;
$scope.year = $routeParams.year;
}
Demo JSFiddle
You could use $location object. Here's a link to the official documentation
And here's a sample of code using it :
if ($location.hash() !== "") {
$scope.date = $location.hash();
$scope.loadData();
} else $scope.initWithDefaultValues();
But your url list should look like this :
**https://mysite/blogs#01/01/2017
https://mysite/blogs#02/01/2017
https://mysite/blogs#03/01/2017
https://mysite/blogs#04/01/2017**
Once you did this, you can also set your browser url this way :
$location.hash( myUrlList[foo].split("#")[1] );
Where myUrlList contains your url list as shown upper.
In order this solution to work, you'll have to declare $http, $location, and perhaps also $anchorScroll depending of what you're doing with your date.
This means that in all other cases that those mentionned in when clauses, the route is redirected to '/'. This solution shows how to use a different controller and route depending on the original url.

pass Algolia id attribute instead of Name Atributre in a post request on Laravel 5.2

Using the Javascript, Vue.js and Typeahead.js way shown by Jeffery Way and Algolia docs to index json objects from the Algolia platform.
Currently when i search for the result i require and hit the submit button, It is passing the name attribute through in the post request.
How is it possible to pass the name and the id attribute or if nescessery just the ID arrtibute would work.
<script>
new Vue({
el: 'body',
data: {
query: '',
users: []
},
ready: function(){
this.client = algoliasearch("MYID", "MYAPI");
this.index = this.client.initIndex('dev_category_list');
$('#typeahead').typeahead(null, {
source: this.index.ttAdapter(),
displayKey: 'name'
});
},
methods: {
search: function(){
if (this.query.length < 3) return;
this.index.search(this.query, function(error, results){
this.users = results.hits;
}.bind(this));
}
}
})
</script>
As a total newcomer the laravel, vuejs and javascript its somewhat difficult to get to grips with the syntax and phrases used when explaining the instructons within the docs so any help would be greatly appreciated.
My indexed objects look like so:
{
"id": "3",
"name": "My Product 3",
"value": "3",
"alternative_name": "Prod 3",
"objectID": "3"
}
Im hoping to pass the value of ID or objectID along with the name attribute in a post request once the user selects the given result from the algolia drop down menu and hits the submit, just the ID would work as mentioned above if its not possible.
Thanks.
--- Update referencing Jerska: ---
Ok so after playing around as a newbie for a little bit i seem to have it working, Im not exactly sure how secure this is or how reliable one would say, Hopefully im not a million miles off from where i need to be. Be good to see what your personal and professional thoughts are.
.on('typeahead:select', function (e, suggestion) {
$('#typeahead').change(function() {
var val = suggestion.id;
$('#st').val(val);
});
I have created a hidden input field and named is 'st' for a demo and on update of the algolia results jquery is using the .change function to append the value to the hidden input fields value. That way the form can be continued and sibmitted as i originally wanted and hoped for, The benefit here is that even if the user is to select a result from algoia drop down menu then continue with the form, If he or she decides they want to go back to the search field and change it, They can do before they submit the form or before any window.location is run, I even thought of using ajax or simply jquery $.post but its working ok the .change
Look forward to hearing your thoughts.
Thanks
If you want to redirect to an item page, the typeahead:select event gives you the selected option :
$('#your-input')
.typeahead(/* ... */)
.on('typeahead:select', function (e, suggestion) {
window.location = suggestion.url;
});
from Algolia redirect to search results
You can access the selected object through the suggestion parameter. You could definitely use something like
window.location = 'YOUR_URL?id=' + suggestion.id + '&name=' + suggestion.name;
This assumes you're using typeahead.js#0.11.
typeahead.js being unmaintained, Algolia recommends to use their own fork of typeahead.js#0.10, autocomplete.js.
Here are the different event names and handlers signatures depending on what library/version you're using:
typeahead.js#0.11: typeahead:select -> function($event, suggestion)
typeahead.js#0.10: typeahead:selected -> function($event, suggestion, datasetName)
autocomplete.js: autocomplete:selected -> function($event, suggestion, datasetName)

Changing data returned from service changes data in service too

When I store data returned from a service in my controller and then edit it, it also changes the data in the service.
JSFiddle Demo
/* The backend connection part and the actual markdown editor JS have been removed because it would just make the code huge and is irrelevant to the problem */
var myApp = angular.module('myApp', []);
// In my app, this service caches blog post data from my server on the client side and returns single posts from it
myApp.factory('PostService', function ($log, $filter, $http) {
var data;
// Just an example for data pulled from server
data = [{
id: 99999,
text: "Hello"
}];
// Function for returning a post out of the data array loaded from the server
var getData = function (id) {
if (id !== undefined) {
var arr = $filter('filter')(data, {
id: id
});
if (arr.length === 0) {
$log.error('PostService:: getData(' + id + '):: Post Not Found');
return 'not_found';
} else {
$log.debug('PostService:: getData(' + id + '):: Post returned');
return arr[0];
}
} else {
return data;
}
};
return {
getData: getData
};
});
function ctrl($log, $scope, PostService) {
var edit = this;
// Sample post id
edit.editingId = 99999;
// "Copy" (apparrently more "bind") the blog post data to edit.data
edit.data = PostService.getData(edit.editingId);
}
This is used for a markdown editor. I wanted to load the data from the service into the controller, then edit it, and give the service the new version on pressing a "Save" button.
If the aforementioned behaviour is correct in the sense of Angular's databinding, what is a better solution to achieve what I want?
Update
Based on PSL's comment and Thibaud Sowa's answer I changed the getData() function to return a copy using angular.copy(). However, it seems not to be possible to copy one object out of an array (like angular.copy(arr[0])), as it will still return the whole array. See the updated JSFiddle.
Update 2
Well, I was dumb. I corrected it in the fiddle. Thank you for your answers.
This is because you are returning an object. In javascript when you do that it's like if you are passing a pointer.
You should use angular.copy to copy the object field by field, like this:
return angular.copy(data);
See the doc here https://docs.angularjs.org/api/ng/function/angular.copy
Response to your update
Well, I edited your fiddle, to show you that you can copy an item of an array. Actually it's seems that every thing works like you want... (Or I didn't understand your need!)
The updated fiddle:
https://jsfiddle.net/thibaudsowa/aybLwa2L/3/
There is a very simple solution to your problem:
If you dont want to change the data you get from the service make a copy
There are plenty of threads on SO discussing the fastes or most elegant way to deep copy a Javascript object. A simple and rather fast solution is using json parse and stringify like this:
var copyOfA = JSON.parse(JSON.stringify(a));
Apply this to the data you get from your service and you are good to go :)

Angularjs - how to set template content from server json answer?

I need to set template of my route dynamic. For examle, I have this config (route):
$routeProvider.when('/page', {
templateUrl: '/dynamic-page',
});
But from /dynamic-page I get JSON:
{
"title": "Title of the page",
"content": "Html-content of the view"
}
I need, to set template from content key of the server answer, and value of the title key I need to pass into controller.
Tell me please, it is possible?
Thank you!
You can achieve this by an alternate approach.
$routeProvider.when('/page', {
template: ''
});
Now you need to get data. That you can do in resolve block in route provider or can call it via ajax in controller.
I have not found the right way to solve the problem, so I decided it so:
in a $rootScope I create pageTitle variable, that contains my page title
i bind pageTitle to the title of my html
from server now I receive only html-content with ng-init="$root.pageTitle='Page title'"

AngularJS POSTs empty requests?

I'm a newbie in AngularJS and I've faced an issue when I try to make a POST request with AngularJS and it POSTs no parameters with it. I use Sinatra as a RESTful interface.
That's how my Sinatra backend looks:
post '/layer/:layer_id' do
#layer = PageLayer.where(id: params[:layer_id]).first
#layer.content = params[:content]
#layer.save
end
If try to POST with Postman chrome extension - it works! Sinatra saves the content properly. So I'm sure that the backend works as it should.
That's how my angular test code looks:
TestCtrl = ($scope, $routeParams, $http, $resource) ->
$scope.layer = []
Layer = $resource('/layer/:id', {id:'#id'})
$scope.layer = Layer.get {id: $routeParams.layerId}, ->
console.log "Got you!"
$scope.saveContent = ->
$scope.layer.$save()
console.log "Saved!"
angular.module('appDirectives', []).directive "test", ->
return (scope, element, attrs) ->
element.bind "blur", ->
console.log("blur!")
scope.saveContent()
And HTML-code:
<div>Content: {{layer.content}}</div>
<div>
<form>
<input type="text" test ng-model="layer.content">
</form>
</div>
So, the only question is: What's wrong? Why I can make correct request with Postman but not with angularJS? Angular returns empty "content" so Sinatra saves it as "" every time.
I've also attached a structure of a layer:
g {id: 27245, page_id: 2302, external_id: 26518, original_upload: null…}
content: "dfgdfg"
external_id: 26518
id: 27245
layerNumber: 8
page_id: 2302
How can I log what exactly angular POSTs?
Hey this is the exact problem I was having, and the answer now seems so obvious. I knew Angular was sending json, but no matter what I tried it wasn't working. This led me in the right direction, but as for parsing json I had to write
ng_params = JSON.parse(request.body.read)
I had to change 'string' to 'read'. Maybe I have a newer version of the json gem or something. My full save process is like this:
post '/api/v1/test' do
ng_params = JSON.parse(request.body.read)
#foo = Foo.new(ng_params)
if #foo.save
puts "Page Saved"
content_type :json
rabl :foos, format: "json"
end
end
I use rabl to format the json to have control over what json data Sinatra sends back (no emails or passwords please)
My Angular code is just this (have not yet implemented put, patch or delete, nor auto update of data just yet. You still have to refresh the page to see the new post.) And to be clear, I have a table named 'foos', where the ActiveRecord model is 'Foo', and one column named 'anything' (other than timestamps and id, which I make sure are always there).
// app declaration
var app = angular.module("App", ['ngResource']);
// data service
app.factory('Foo', ['$resource', function($resource) {
return $resource('/api/v1/test/:id', {id: '#id'});
}]);
// the controller
app.controller('Controller', function($scope, Foo) {
$scope.foos = Foo.query();
$scope.create = function(anything) {
Foo.save({anything: anything}, function(foo){
$scope.foos.push(foo);
});
};
});
Then in my markup the form looks like this, where the important thing is the call to 'create' with 'anything' as the argument in 'ng-submit'. If you have more than one column in your table you call 'create' with more than one argument ex. 'create(anything, bar)'.
<h3>Add something new</h3>
<form ng-submit="create(anything)">
<input ng-model="anything" type="text">
<button type="submit">Do it</button>
</form>
While displaying the data is
<li ng-repeat="foo in foos">
<p>{{foo.anything}}</p>
</li>
This link solved the problem. Just add
gem 'rack-parser'
to your Gemfile and add this code to config.ru. Will work like a charm.
require 'rack/parser'
use Rack::Parser, content_types: {
'application/json' => Proc.new {|body| JSON.parse body }
}
All right, I've solved the issue. Somehow Sinatra was not properly getting POSTs from Angular and was not automatically putting them into params.
So if we parse the request manually - it works. Like that:
post '/layer/:layer_id' do
#updated_layer = JSON.parse(request.body.string)
#layer = PageLayer.where(id: params[:layer_id]).first
#layer.content = #updated_layer['content']
#layer.save
end

Categories

Resources