Trying to log to Google Analytics the selected option on an ng-repeat list in Angular 1. For example, if the list is 1;2;3;4, the user selects 1, and this is passed to Google Analytics.
I gather that you need to define the function as ng-click to pass, but still can't work it out.
In the HTML:
<li ng-repeat="cars in x" ng-click="myFunction(GA)">
JS:
$scope.doClick = myFunction(GA, ga, $window){
$window.ga('send', 'event', click, { cars.x });
}
This is frustrating me a loot, so if someone could help I'd be truly grateful.
The idea of Angular is that it is a MVC. This being the case, the HTML doesn't have an idea what $parent is and you need to have a common 'scope' between the HTML and the Javascript. This is why there is the built in $scope so if in my controller I had $scope.newX = $parent.x then in my HTML I can pass ng-click="myFunction(newX)" and it will pass it the value of the $scope.newX
Related
I have millions of record which I need to fetch and bind it to my select dropdown in my angularjs application. But, as we know obviously it'll cause the performance issue. So I'm looking for the serious solution as like a ui-grid infinite scroll functionality in select dropdown.
HTML Template:
<select ng-model="zipCode" ng-options="zip.FZIP as zip.FZIP for zip in zipCodes | limitTo: totalDisplayed" ng-init="zipCodeInit()" ng-change="loadMore(totalDisplayed);"></select>
Controller Code:
$scope.totalDisplayed =1000;
$scope.loadMore = function (startCount) {
var endCount=startCount + 1000;
$http.get('api/get-zip-codes?rowStartCount=startCount&rowEndCount=endCount').then(function(response){
$scope.data = $scope.data + response.data;
$scope.totalDisplayed += 1000;
});
};
Here my problem is to make a call to loadmore function on scroll of my select dropdown. My current implementation is ng-change.
Any Idea or the solution will be helpful to make my expected change on this select dropdown.
Use this jQuery plugin it will help you
http://jscroll.com/
You can refer Solution For Very Long Dropdown Menus.
This would help, it has all the code as well visuals.
I just realise that we can't have such dynamic dropdown to load data on scroll and this was the requirement because of bulk records such 2Lakhs+ records to be listed. And to overcome this problem I have used predictive search/auto complete text box which works with me perfectly based on the user input.
Thanks for the Answers.
I am developing an app that works with a "Widget layout".
The user gets a page which is a Dashboard with different widgets he can interact with, such as a table, graphs etc.
I am adding a global "filter" using <md-chips>, the objective of this is having filters that are shared by all the widgets and can be updated by all the widgets.
My Filter list uses <md-chips>, with read-only and md-removable set to True. So filters can only be deleted, or added by interacting with the widgets (so only added programmatically).
One of the feature of this "module" is to add a new filter on a field when a Graph element is clicked.
Example :
Here is my Filters list before clicking a Graph element
Now I click on a Graph element which is in a Child controller of my Filter controller, it will $emit an event to say to the global controller : "I want to update the filters ! here is the filter to add"
And the Filter Controller will get that event and update his filters accordingly ($scope.tags is the list of filters and the model used in <md-chips>)
// CHIPS
$scope.tags = [];
$scope.readOnly = true;
$scope.removable = true;
// FILTER LISTENER
$scope.$on('filterChildChanged', function (event, filter) {
$scope.tags.push(filter);
console.log($scope.tags);
console.log("Parent event fired !");
});
At that point I would expect the <md-chips>element to refresh, because $scope.tags just got a new filter :
<md-chips
ng-model="tags"
readonly="readOnly"
md-removable="removable"
id="filters">
<md-chip-template>{{$chip.value}}</md-chip-template>
</md-chips>
But instead, nothing happens! and the weird part is, it refreshes when I click on one of the existing chip (I had a "test" chip) !
TESTS :
So when I push a test chip on the array before rendering :
$scope.tags.push({field: "testField", value: "test"});
And click on a bunch of Graph elements, $scope.tags is perfectly updated, BUT the visual stays the same until I select the chip "test", then all the <md-chips> appear just like it triggered some refresh function.
Any hint on why the <md-chips> element is not refreshed as $scope.tags (its model) is updated BUT is updated when a chip is selected ?
I tried to trigger md-on-select to force this behavior to happen every time I add a new filter to $scope.tags but I got no luck so far !
Thanks for reading !
NOTE : I am using the latest version of Angular MATERIAL (HEAD MASTER) see doc here : https://material.angularjs.org/HEAD/ | built from the GitHub repository.
EDIT : The problem comes from $$hashKey not being added to the objects, they are only added when I click on one of the existing tags, I need to find a way to add this $$hashKey attribute when I add a new filter
The problem came from the absence of $$hashKey when I added a new filter to my filters model for my chips ($scope.tags).
So I just needed to change
$scope.tags.push(filter);
to
$scope.$apply(function () {
$scope.tags.push(filter);
});
And here is my console.log test
Good thing I learned :
the <md-chips> directive only knows it needs to be updated if its <chip> objects have a $$hashKey
See this on scope.$apply
Plunkr
I made a autofill dropdown using angular custom directive.All is working fine.
But I want to make this directive reusable!!!!
Currently my directive is tightly depended on Id and Name property of selected item.
I want to assign text property(Which I want to bind the text into list items html) and value property(which will be available in my app controller) like textfield="Name" and value-field="Id".
Imagine If my data object does not contain Name or Id property , my
directive would not work.
HTML:
<autofill-dropdown items="searchCurrencies"
textfield="Name" valuefield="Id" selected-data="Id" urllink="/api/SetupCurrency/Autofill?filter=">
</autofill-dropdown>
Template :
<div class="pos_Rel">
<input placeholder="Search Currency e.g. doller,pound,rupee"
type="text" ng-change="SearchTextChange()" ng-model="searchtext"
class="form-control width_full" />
<ul class="currencySearchList" ng-show="IsFocused && items.length">
<li class="autofill" ng-repeat="item in items" ng-click="autoFill(item)">
{{item.Name}}
</li>
</ul>
</div>
So,finally what I want to accomplish , I'm going to bind Name property(or other,depends on what value I set to "text-field" attribute onto my html) to listitems and whenever user select an item, it will give me the selected Id(or other property ,depends on what value I set to "value-field" attribute onto my html).
Plunkr Here
Update:
I think my question not so clear.
I have written same directive 2 times to accomplish and also 2 times same template :(
Please look through my updated plunkr.
Updated Plunkr
I want to say that I am not quit sure if I understood your question in the right way so I try to repeat it.
textfield="Name" valuefield="Id" selected-data="Id"
You want to store the Value of the Property of the selected Item of your custom directive.
The Value should be stored in the Variable provided in the attribute "textfield"
The attribute "valuefield" should define the name of the property of the selected Object
If this is the case you have to get rid of the two-way databinding for your valuefield. Because you only want to provide a String (like "Id" or "Name").
I altered your plunkr again. First of all I made the new scope variables:
scope: {
'items': '=',
'urllink':'#',
'valuefield':'#',
'textfield':'=',
'Id':'=selectedData'
}
Valuefield is now only a text binding. So if you want to change it in the angular way you have to provide a scope variable outside of the directive and a '=' twoway binding inside :D
$scope.autoFill = function (item) {
$scope.IsFocused = false;
$scope.searchtext = item.Name;
$scope.Id = item.Id;
$scope.textfield = item[$scope.valuefield];
}
Also I added the last expression to your autofill function. The name of the property (valuefield) will be written into the textfield variable which is linked with your outside scope (in this case "Name"):
textfield="Name"
If this is not what you asked I am sorry but I am new to stackoverflow and I still can not comment :P
https://plnkr.co/edit/zE1Co4nmIF3ef6d6RSaW?p=preview
Simplified problem
I have a store. For a product to be included in the store there needs to be a shelf for it. So, to add a new product to the store the workflow is:
Add a shelf
Add product to that shelf
(The workflow can not be changed)
Realization
The shelf is realized by a row in a table, which in turn is controlled by an Angular.js controller (each shelf is an object in an array). To add an product the user selects "create product" in a drop-down menu that is present on each row. This will show an bootstrap modal where I have from a controller added a tab for each product that is possible to add (since each product needs configuration :) ) , then when the user presses a "create" button in the modal a JavaScript method is called interfacing a REST interface to add the product (the UI is updated by a Socket.io event send from the server when the product has been added successfully.
Problem
The JavaScript method (CreateProduct) needs to now what row (R) was affected as well as what tab (T) was selected so that the "onclick" method for the button is CreateProduct(R, T);
My current solution is pretty ugly imho, I have two global variables for R and T, then I use jQuery to capture show event and tab event from the modal, the link in the dropdown has a field "data-row-id" that is identifying the row
HTML (Jade) snippet from dropdown menu:
a(data-toggle="modal", href="#createProduct", data-row-id="{{row.RowID}}") Create Product
JavaScript:
var R = null;
$('#productModal').on('show.bs.modal', function(e) {
R = $(e.relatedTarget).data('row-id');
});
var T = null;
$('a[data-toggle="tab"]').on('shown.bs.tab', function (e) {
T = e.target.text;
});
I hope there is a better solution to this, I probably am just thinking a bit upsidedown due to inexperience with Angular.js , perhaps there is a way to pass these through the model? Perhaps add these to the modal controller, but then, how to pass the row? My dream would be something like this on the button code
button(type="button", class="btn btn-default", data-dismiss="modal", ng-click="storeCtrl.CreateProduct({{modalCtrl.shelf, modalCtrl.Product)") Create Product
I found a better way (at least I don't need to use jQuery) using ModalService
I created a CreateProductModalController having a variable selectedProduct, this is set on a ng-click event in the tab
ul(class="nav nav-pills", id="tabContent")
li(ng-repeat="prod in products", ng-class="{active: $index == 0}", ng-click="activateTab(prod.name)")
a(href="#{{prod.name}}", data-toggle="tab") {{prod.name}}
The ModalService is called with the rowID that was clicked.
The only problem I have now is that all must be in $scope, I want it to be more encapsulated
I have a view in which I need to insert form fields, into view.
Now these form fields I need to render come f from API request, which basically tells name of field and input type.
So not only I need to insert the template but also fill up input properties basically name attribute.
I am thinking of loading into data into partials, but I am not sure how to load partials dynamically unlike use ng-include
Any help?
Use directives.
You can attach your html template (I'm assuming this is what you mean by partials) to a directive as follows:
.directive('myFormField1', function() {
return {
template: '<label>{{ my_label }}<input></input></label>'
};
});
Then, you can issue your request and bind the data to your scope:
$http.get('/myUrl').
then(function(response) {
$scope.reqData = response.data
}
Finally, you use the request data to dynamically generate your form in the main template. Substitute your own variables and conditions as appropriate.
<form>
<div myFormField1 ng-if="reqData.shouldShowField1 == true"></div>
<div myFormField2 ng-repeat="item in reqData.repeatedData"></div>
</form>
This should point you in the right direction, though without knowing specifics I obviously can't give you a full answer.