how to create reusable component in angularJS? - angularjs

I have two controllers at the moment, one is a form where a user inputs a value and the other is a graph that renders based on an api search. I would need to refresh or re run the second controller based on the input from the first. I am almost certain this is bad design on my part but have not found the ideal way to do it.
HTML code:
<html>
<body>
<!-- this is the graph generator-->
<div ng-controller="GraphAppCtrl"></div>
<!-- this is th form submittal section-->
<div ng-controller="FormCtrl" id="FormCtrl">
<form novalidate class="simple-form">
Name: <input type="text" ng-model="tech"/><br />
<button ng-click="submit(tech)">Submit</button>
</form>
</div>
</body>
</html>
Angular Code:
var app = angular.module('testApp', []);
app.controller('FormCtrl', function ($scope) {
$scope.submit = function(tech){
// Need to be able to call the function that generates graph and pass it the tech value
}
}
app.controller('GraphAppCtrl', function ($scope) {
//here I do a bunch of stuff to generate graph, like http request from third party api etc.
}
What is happening now since I have a reference to the graph controller in the my index.html page it renders the first time based on default parameters, but I would need it to render based on the submit.
I have looked Directives and experimented with the answer in this question but it seems as Directives more of a solution to pass data between controllers rather than what I am trying to do.

You should create an Angular Service
https://docs.angularjs.org/guide/services

Related

Open multiple instances of same partial view and controller in angularJS

I am developing single page application using partial views and angularJS.
I am having a scenario where I have to open same partial view multiple times with different data.
I tried to make controller name dynamic by adding app.directive and changing controller name both in js and html and then calls Angular-Complies method, but the issue is that it changes it for all previous tabs opened.
Then I tried to make multiple js files and changing controller name in partial view with Jquery but still does not helps. Here is my code.
HTML:
<div ng-app="myApp">
<!-- this is in view1.html -->
<div ng-controller="DashboardDesignerController">
<div ng-repeat="widget in workspace.widgets">stuff here
</div>
</div>
<!-- this is in view1.html -->
<div ng-controller="DashboardDesignerController">
<div ng-repeat="widget in workspace.widgets">stuff here
</div>
</div>
//Angular controller is in separate JS file.
app.controller("DashboardDesignerController" , function ($scope, $http,
$rootScope, $compile, $injector, $timeout) {
}
I expect to behave every tab separately according to its data but currently when I go to first opened tab, it's scope changed with the last opened tab.
Is there built in way of angularJS to doing it, Or some good approach will also appreciated.
Actually the issue was, I was calling chart drill down method in core JavaScript which was replacing $scope with last opened.
Resolved the issue by getting scope with JQuery
var scope= angular.element($('.k-state-active').find('.tempDiv')[0]).scope();
and called angular function with this scope variable.

ASP.NET Webforms and AngularJS

I'm still struggling to get my first ASP.NET WebApi / AngularJS app up and running...
I'm trying to query a WebAPI service (which I've written and verified using Fiddler that it works just fine) from Angular, and I'm trying to show the data returned on my ASP.NET Webforms page. I studied a great many tutorials and Pluralsight courses, and really thought I knew how to do it - but Angular doesn't agree with me :-(
I have my Angular app/controller here:
var app = angular.module('MyApp', []);
app.controller('MyCtrl', function ($scope, $http) {
$scope.model = [];
//Call to web API
var Url = 'http://localhost:13811/api/v1/mydata';
$http({
method: 'GET',
url: Url
}).success(function (MyList) {
$scope.model = MyList;
}).error(function () {
});
});
My (very limited) JS/Angular understanding is that this defines an Angular app and a controller, and that if I add this controller to a DOM element on my ASPX page, the controller will be invoked, will make that call out to my WebAPI service (and I do see that this is happening), and then stores the results (a list of some data objects from the database) into the $scope.model variable.
So I was assuming that I would be able to integrate this into a blank ASPX something like this:
<%# Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="DemoAngular.Default" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>Angular Demo</title>
<script src="Scripts/angular.min.js"></script>
<script src="Scripts/app/plz-controller.js"></script>
</head>
<body ng-app="MyApp">
<form id="form1" runat="server">
<div ng-controller="MyCtrl">
<span>Angular says: {{1+2}} </span>
<div class="list-group" data-ng-repeat="x in model">
<div class="list-group-item">
<span>{{x.Field1}}</span><br/>
<span>{{x.Field2}}</span><br/>
</div>
</div>
</div>
</form>
</body>
</html>
I was assuming that adding the ng-app="MyApp" directive to the <body> tag would link the ASPX page to the Angular app, and adding the ng-controller="MyCtrl" to that <div> would then instantiate the Angular controller (and thus make the WebAPI call - this it does, I see that in the F12 developer tools).
I was also expecting that by using the data-ng-repeat="x in model" directive, I would be able to iterate over the list of data elements returned from the WebAPI call, and using the {{....}} syntax, I was hoping to be able to access the individual fields of those objects and display them.
ALAS: I do see Angular says: 3 at the top of my page, so Angular appears to be "there" and active, and I do see the WebAPI call in the F12 developer tools (and I can verify that the expected number of data elements is being returned) - yet no matter what I try, I cannot find any way to actually SHOW that data having been retrieved from WebAPI on my ASPX page......
Any ideas? What am I missing? Must be something really stupid - I'm sure - but I just don't see the forest for the trees anymore........
Fire up the debugger and put a breakpoint on the $scope.model = MyList line. Chances are that you're getting an http response object back here and you need to change it to something like $scope.model = MyList.data. Examining the object in the debugger will tell you for sure if this is the case.

Bootstrapping the same app multiple times in Angular

I'm working on a project where a lot of the UI elements are separate widgets that could be used multiple times on a page. One of those widgets is a shopping cart, where I have a large view (that's present on only one page) and a small view (that's present on every page).
The page where both the large and small view of the cart is visible breaks. I've narrowed it down in Angular to the fact that both apps are bootstrapped (using angular.bootstrap()) but two different scopes are created. This causes loading errors.
I've reproduced the situation here. Even though the apps are bootstrapped, the $scope of one app isn't equal to the other. This is good, but is there a way that I can reference a module in angular.bootstrap so that two ngApps will share the same $scope?
The test HTML
<div data-app="multipleApps">
<div ng-controller="testCtrl">
<p ng-bind="testVar">a</p>
<input type="text" size="25" ng-model="testVar" />
</div>
</div>
<div data-app="multipleApps">
<div ng-controller="testCtrl">
<p ng-bind="testVar">a</p>
<input type="text" size="25" ng-model="testVar" />
</div>
</div>
The Javascript
angular.module("testApp", []).controller("testCtrl", function ($scope) {
$scope.testVar = "Ready...";
});
angular.bootstrap(document.querySelectorAll("[data-app='multipleApps']")[0], ["testApp"]);
I already tested using the injector returned from angular.bootstrap(), but this raised an a.unshift is not a function error from AngularJS.
var els = document.querySelectorAll("[data-app='multipleApps']");
if (els.length > 1) {
var injector = angular.bootstrap(els[0], ["testApp"]);
for (var i = 1; i < els.length; i++) {
angular.bootstrap(els[i], injector);
}
}

Angularjs | how to get an attribute value from element in which controller is defined

I'm still fighting with simple things in Angular. I have jQuery and Backbonejs background, so please do not yell on me. I try hard to understand differences
I have HTML in which from rails is given ID of project as data-project-id:
<div data-ng-controller="ProjectCtrl as ctrl" data-project-id="1" id="project_configuration">
Is there any chance to get access to this attribute? I need it to my API calls...
To access an elements attributes from a controller, inject $attrs into your controller function:
HTML
<div test="hello world" ng-controller="ctrl">
</div>
Script
app.controller('ctrl', function($attrs) {
alert($attrs.test); // alerts 'hello world'
});
In your example, if you want to get data-project-id:
$attrs.projectId
Or if you want to get id:
$attrs.id
Demo:
var app = angular.module('app',[]);
app.controller('ctrl', function($attrs) {
alert($attrs.test);
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app" ng-controller="ctrl" test="hello world">
</div>
In Angular world you should use directives to manipulate with DOM elements. Here a nice explanation how to get attribute value from custom directive (How to get evaluated attributes inside a custom directive).
But if you still want to get it's value from controller you are able to use jQuery as well $('#project_configuration').data('project-id')

Angular binding for dynamically added html div

Sorry, this seems a duplicated questions, but I tried all answered questions close to my question, with no success.
I am trying to introduce angular.js into a legacy system.
the system is using the .load jquery function to dynamically load div content with a page from an ASP.NET MVC page.
my brief html will look like this
<body ng-app="myApp">
<div ng-controller="myCtrl">
any content...
<div id="dyncontent"> </div>
</div>
and my javascript legacy code looks like
$('#dyncontent').load('/showviewcontent');
I added in the dynamic content, some angular directive and binding instruction
my angular code is like this
var myApp = angular.module('myApp', []);
myApp.controller('myCtrl', function ($scope) {
.....
});
How to make the binding / angular directive works on the newly added content?
You need to manually start the angular module using angular.bootstrap
$('#dyncontent').load('/showviewcontent', function() {
angular.bootstrap(document.getElementById('dyncontent'), ['myApp']);
});

Resources