tldr;
I need to fire a custom directive/jQuery plugin on ng-click and pass a parameter to it then reload that page so the parameter's value takes place. So on reload instead of there being 3 results in my Google Map, there should be 50 results showing.
Disclaimer
I've done a ton of reading on firing directive on ng-click as well as passing parameters to directive (particularly this question and this question and this question) but I am fairly new to AngularJS so I'm still a bit naive to all the greatness of Angular and how to utilize it properly...
Background
I created a jQuery plugin for a Google Maps API app I'm creating. The app is using AngularJS also. The plugin creates a map and shows 3 locations to the user plugin code here. Under the map I have the list of 3 locations in a table. I also have a button that says more results which should return 50 more locations.
Question
What is the best way to...
Pass a new parameter to my plugin/directive? Currently on page load I load the directive and fire the plugin by <div tfinder-map="{queryLimit: 3}">. Ideally I'd like to be passing 50 when I click the more results button.
Along with passing the param to my directive/plugin on click of more results, I would like it to essentially fire the directive and reload the page so the 50 results show up, instead of just 3.
After reading other questions, I think passing a param to my directive would go something like this (although I'm sure the syntax is wrong):
ng-click="tfinder-map(queryLimit: 50)"
And to be able to persist that value as the page reloads, the only way I could think to do that would be via a query string argument in the URL.
I also did a little reading about $route.reload() which sounds interesting, I just don't know the best way to implement this to do a reload with params.
The code
My current directive looks like this:
directive('tfinderMap', function() {
return {
restrict: 'A',
link: function(scope, elm, attrs) {
$(elm).tfindermap(scope.$eval(attrs.tfinderMap));
}
};
})
And in jQuery it'd be
$('#foo').tfindermap({queryLimit: 3})
The actual jQuery plugin can be viewed here on Github
Also, here's the UI if it helps visualize it
clicking the more results button should make 50 results appear as opposed to 3
Related
Providing parameter to navigate back function in a Kendo View
According to the Kendo UI documentation, you can easily navigate backwards to the previously visited mobile View using the following function:
app.navigate("#:back");
With default navigation it's quite easy to provide parameters, like app.navigate("#my-view?id=xxx&foo=bar"). However, is it possible to provide a parameter to the back function? Meaning something like this (fictional) example:
app.navigate("#:back?pageIndex=5");
If not, are there any other smart suggestions to look into? Obviously, my pseudo sample doesn't work.
The reason is that all my views are seperated in loose files and the page that calls the back function works somewhat like a dialog: sometimes it should provide arguments back to the previous view. And sometimes not. In the fictional example, I want to basically intercept certain functions in the 'parent view' if certain parameters are provided.
Despite the fact that using a ModalView would normally be a better fit here, or even a decent global datasource, I'm curious about this one.
I'm starting my great adventure with angular and wanted to ask a question regarding directives usage, as I am not 100% sure after seeing multiple tutorials.
I want to make a simple app giving you directions:
1) click a button, fire in the controller a function to get current position from navigator geolocation (i think no service is necessary for this, and this can stay in the controller?)
2) after getting the coordinates I have some information about the place, which should be shown to the user, and here is the question: Should there be a directive with template for binding these information from the scope and showing in the dom, or is it enough to use simply "ng-hide" (which is in fact a directive - sic!:)) on a div, fetch the information on a place with a service, bind it with the hidden div, and set "ng-hide" to false to display the dom containing place information.
The "ng-hide" variant seems easy, but is it the proper "angular way" or just bad practice of beginners?
Thank You for your time and help in advance:)
IMHO
You can put it in a service if you want to use that method from different controllers or for clean-code purpose.
I use directives when I want a specific behaviour or a group of controls that repeat along the application. If you are using basic html controls and you just need to display/hide I would use ng-hide.
I have something like this plunker. I would like my view to get populated with the mapId that gets passed into the directive. Then I would like to show that view in place of "This is some content".
First how can I pass the mapId into the view and secondly how can I then show that view in the lightbox div?
I know this is kinda vague but I'm new to angular so I don't know what other information is needed here.
You're not going to be able to use the view.html file with the current lighbox code. It would need to be heavily modify to make use of template files and isolate scopes. However, you can use the current code to achieve the same thing with perhaps the addition of a controller to modify the scope.
I've modified the index.html in the plunker so that it displays the mapId value.
Let's go over what angular-lightbox is actually doing:
By returning just a function, the directive is going through the whole compile process and then using the returned function as the linker. The linker then goes on to (depending on the options) add an overlay (the opaque dark background of the lightbox) to the DOM & then add the lightbox active class to div#lightbox. This div is already in the DOM, but hidden due to the CSS, and has been already compiled & rendered by AngularJS so it can't really be changed other than through two-way data binding at the same or child scope level.
What my changes did:
I added a bound scope variable to div#lightbox called mapId and added an ng-click to the buttons that sets the value of mapId to 1, 2, or 3. So when you click on the button, div#lightbox is revealed & the value of the new value of mapId is shown.
Given that the above is probably not what you want to accomplish...
Let's talk about how to go about doing that
First you will need to load view.html into the directive somehow. Either by just having the view.html contents be a string inside the directive or use $templateCache.
You will then need to $compile the HTML from view.html, passing in a new scope that contains the values you want from options, and then append it to div#lightbox.
I would use a modal from Angular-UI bootstrap http://angular-ui.github.io/bootstrap/, and adapt it for my case. I think this is a good starting point.
I'm building a website where I need to display Facebook like/ share buttons and a twitter share button on several elements in a list. Basically I have a list of events that are loaded asynchronously using an an angular controller and ng-repeat.
The problem I am encountering is that twitter and Facebook buttons require a js widget now and some js code needs to be executed to make the buttons display. This would be fine if the events were rendered server side, but they are instead done so using angular, and I need to have that js code executed after the events are rendered.
Essentially, my question is: how could I run some code each time after an ng-repeat is rendered in angular?
Thanks guys
Solved this using directives, basically just added this to my javascript:
myApp.directive('afterEventsLoadedDirective', function() {
return function(scope, element, attrs) {
if (scope.$last){
// handle events here
}
};
});
I've assembled a modestly sized application and I am in the process of factoring code to reduce the overall number of maintained lines, as well as performance tuning. The use case that has me posting this question is that I have a button embedded in a menu that invokes (or needs to invoke) a method on a controller that displays a form. This currently is implemented using a direct reference to the specific button control, creating a panel, and putting that panel inside of my viewport.
The question at: ExtJS 4.1 Call One Controller From Another begins to address the issue of best-practices near the end of responses, but doesn't really settle on a base-case that can be reproduced or extended to cover more complex implementations (which is the aim of my question.)
Given the two controllers:
A "main menu" controller.
// controller/Menu.js
Ext.define("App.controller.Menu", {
extend: "Ext.app.Controller",
init: function () {
this.control({
"viewport > mainmenu > button": function (ctl, evt) {
}
});
}
});
A user account controller
// controller/User.js
Ext.define("App.controller.User", {
extend: "Ext.app.Controller",
stores: ["User"],
views: ["user.Edit", "user.List"],
init: function () {
}
});
The Question
What would be the (best) way to implement a crosswise connection between the two controllers to properly delegate the responsibility of responding to a click event on the menu button for "Create a New Account?"
One Possible Solution
Using componentquery I can easily narrow down the focus of the button in the main menu view using a tag property such that the User controller is responding directly to the event:
// controller/User.js
"viewport > mainmenu > button [tag=user.create]": function () {}
An unknown alternative
Or I could possible winnow my way through the object graph to find the reference to the User controller from the Menu controller and invoke it that way.
// controller/Menu.js
// switch on tag case "user.create"
App.controller.User.createUserForm()
The real question
The question that results from all of this is what the "most acceptable" solution is here. One could imagine the use of a third, mediating controller, to "route" requests from controls to controllers but I think that goes against what the remainder of the framework is attempting to do. Using a variation of either of these methods currently works however neither feels completely clean and reliable; or ultimately maintainable long-term (as code gets spread out rather quickly.) Additionally the thought had occurred to us to drop into raw events but we run into the same kind of maintainability issues there.
Some short lines:
A thing that I don't understand is that Sencha Touch has routing but no eventbus where ExtJS has a event bus but no routing... (and there are more points where the MVC implementation differ) Whatsoever, because I am using ExtJS most of the time I created a custom routing to fill this gap for me. Maybe sencha will add this in version 5.
The easiest and quickest solution: use the getController() of the Ext.app.Application controller to invoke the responsible controller from your menu controller.
The (imo) best solution: write yourself a router where each controller register it's routes to and use both; routing and eventbus. This gets really handy if your app have shared components that are used by more than one dev team.