I am new to Angular. I went to intro-tutorials on some website.
There I learned that I can access controller functions and controller-local variables using controller-name and without $scope service. Like for example:
<div ng-controller="someController">
someController.someFunction()
someController.someVariable
</div>
I my simple application I have written a controller in controllers.js and using it in home.html. I have defined the mapping in app.js
I provided a button tag for it in html but the controller function is just not responding.
Looking at my js and HTML page you will know what I am trying to accomplish.
Here' controllers.js:
app.controller('welcomeStoryPublishCtrl', ['$log','$http',function($log,$http){
this.wsPublish = {};
this.publishGroup = function(wsPublish){
console.log('here');
$http({
method:'POST',
url: 'http://localhost:9090/Writer/publishStory',
header: {'Content-Type':'application/json'},
data: wsPublish
});
};
this.public = function(){
console.log('from public');
};
}]);
home.html
<html>
<head>
<script src="js/angular.min.js"></script>
<script src="js/angular-route.min.js" ></script>
<script src="https://jspm.io/system#0.16.js"></script>
<script src="js/app.js"></script>
<script src="js/controllers.js"></script>
</head>
<body>
<div>
<div id="welcomeStory">
<span id="wsTitleBub">Title</span>
<input id="wsTitle" type="text" ng-model="wsPublish.welcomeStoryTitle" />{{wsPublish.welcomeStoryTitle}}
<h6>Words..</h6>
<textarea id="wsWords" ng-model="wsPublish.welcomeStoryWords"></textarea>
<input id="wsPublish" type="button" name="wsPublish" value="Publish" ng-click="pub = !pub" />
<input id="wsAddShelf" type="button" name="wsAddToShelf" value="Add To Shelf" ng-click="addToShelf()" />
</div>
<div id="wsPublishTo" ng-show="pub">
<ul>
<li>
<input type=submit id="wsgroups" value="Group" ng-click="publishGroup(wsPublish)" />
</li>
<li>
<button id="wsPublic" ng-click="public()">Public</button>
</li>
</ul>
</div>
</div>
</body>
</html>
I know that I can do this by injecting $scope module dependency and I know controller instantiation always creates a $scope object itself.
But what if try doing so like this? What am I doing wrong here?
And here is app.js:
angular.module('Writer', ['AllControllers','ngRoute'])
.config(['$routeProvider', function($routeProvider,$Log){
$routeProvider.when('/Diary',{
templateUrl:'pages/login.html',
controller: 'LoginFormController'
})
.when('/loginPg',{
template: 'Hello from app.js'
})
.when('/home',{
templateUrl: './pages/home.html',
controller: 'welcomeStoryPublishCtrl'
})
.otherwise({redirectTo : '/Diary'});
}]);
First off all your input elements are not wrapped in a <form> tag and this is why your button should not be working properly. If you insist to use <button> it should be in a <form> tag so it "submits" the form, if not, go with <input type="submit"..>
Lastly, i would suggest you to use services for your http requests as this is a common good practice. :)
In your HTML you have not mentioned the ng-app directive neither have you mentioned your controller directive ng-controller.
Your HTML
<body ng-app="someApp">
<div>
<div id="welcomeStory" ng-controller="welcomeStoryPublishCtrl as wsCtrl">
<!-- Rest of your code -->
<button ng-click="wsCtrl.public()">Public</button>
Your JS
var app = angular.module('someApp', []);
app.controller('welcomeStoryPublishCtrl', ['$log','$http',function($log,$http){
this.wsPublish = {};
this.publishGroup = function(wsPublish){
console.log('here');
$http({
method:'POST',
url: 'http://localhost:9090/Writer/publishStory',
header: {'Content-Type':'application/json'},
data: wsPublish
}).success(function(data){
console.log('run success!');
});
};
this.public = function(){
console.log('from public');
};
}]);
Hope this helps.
Are you missing ng-app attribute ?
Related
any help about who insert html with Angular code inside the html string.
Example:
<div class="container">
<span class='btn' onclick="javascript: clicklink()">click here</span>
<div name="content" id="content">
</div>
</div>
<script>
function clicklink(){
$("#content").html("<span class='label label-danger'>Invoice</span>"+
" <div ng-app ng-init='qty=1;cost=2'> <b>Total:</b> {{qty * cost | currency}} </div>");
}
</script>
Example click here
If you're looking for a 'Hello World' kind of example, this is probably as basic as it gets.
https://code-maven.com/hello-world-with-angular-controller
Maybe the example doesn't make sense, but here is the thing maybe exist another way to do that. I have a project with c# MVC and for render some Views I use ajax
Javascript to load modal into View:
function Edit(){
$.ajax({
url: '../Controller_/Action_',
type: 'POST',
datatype: "html",
traditional: true,
data: { data1: data1 },
success: function (result) {
$('._container').html(result);
},
error: function (result) { }
});
}
MVC c# code:
public ActionResult Edit()
{
...\ code \...
return PartialView("/View/_Edit", model);
}
View Main:
Open Modal
<div name="_container">
<!-- Here load body of modal -->
</div>
Partial view (Edit) return by Action (Edit) in Controller . Should be a modal structure:
<div name="_editModal">
#html.LabelFor( x => x.Name)
#html.EditorFor( x => x.Name)
<div ng-app ng-init="qty=1;cost=2">
<b>Invoice:</b>
<div>
Quantity: <input type="number" min="0" ng-model="qty">
</div>
<div>
Costs: <input type="number" min="0" ng-model="cost">
</div>
<div>
<b>Total:</b> {{qty * cost | currency}}
</div>
</div>
</div>
As already stated by a bunch of people in the comments and other answers this is absolutely bad practice. But there is also a built-in option to solve your problem with pure AngularJS using $compile.
In order to make that work you need to place everything inside a controller or directive and inject the $compile service accordingly.
You need to use the $compile service to produce a function of your dynamic HTML markup which is able to consume a scope object as a parameter in order to produce a working AngularJS template.
After inserting your template, you need to trigger the AngularJS digest cycle using $apply.
<div class="container" ng-controller="MyController">
<span class='btn' ng-click="clicklink()"">click here</span>
<div name="content" id="content">
</div>
</div>
<script>
app.controller("MyController", function($scope, $compile) {
var template = "<button ng-click='doSomething()'>{{label}}</button>";
$scope.clicklink = function(){
$scope.apply(function(){
var content = $compile(template)($scope);
$("#content").append(content);
});
}
});
</script>
This code works:
<div ng-include src="'Test.html'"></div>
This code doesn't:
<div ng-include src="ctrl.URL"></div>
(ctrl.URL is set to "Test.html"). I also set it to 'Test.html' and "'Test.html'" with the same results.
How can I successfully convert this into an expression for use in ng-include src? I think I am missing some knowledge on how strings get parsed but I was pretty sure 'Test.html' should work.
I found that I am too incompetent to rename my own variables. ctrl.URL was really ctrl.URl. Now everything is working.
Check this, maybe this fiddle will help you.
HTML and templates:
<div ng-controller="Ctrl">
<select ng-model="template" ng-options="t.name for t in templates">
<option value="">(blank)</option>
</select>
url of the template: <tt>{{template.url}}</tt>
<hr/>
<div ng-include src="template.url" onload='myFunction()'></div>
</div>
<!-- template1.html -->
<script type="text/ng-template" id="template1.html">
Content of template1.html
</script>
<!-- template2.html -->
<script type="text/ng-template" id="template2.html">
<p ng-class="color">Content of template2.html</p>
</script>
The controller:
function Ctrl($scope) {
$scope.templates = [{
name: 'template1.html',
url: 'template1.html'},
{
name: 'template2.html',
url: 'template2.html'}];
$scope.template = $scope.templates[0];
$scope.myFunction = function() {
$scope.color = 'red';
}
}
I use ui-router to route to particular sub page as needed:
var myApp = angular.module("myApp",['ui.router']);
myApp.config(function($stateProvider, $urlRouterProvider) {
$stateProvider
.state('usergroups', {
url: "/usergroups",
templateUrl: "pages/usergroups.html",
controller : 'UsergroupsCtrl'
})
.state('usergroups.create', {
url: "/create",
templateUrl: "pages/usergroups.new.html",
controller : 'UsergroupsCtrl'
})
...
This is my usergroups.html:
<body>
<h3>User Groups</h3><br/>
<button class="fon-btn" type="button" ng-hide = "toAdd" ng-click="toAdd = true" ui-sref="usergroups.create">Create New Group</button>
<div ui-view></div>
<ul>
<li class="bitcard padding10" ng-repeat="group in usergroups">
<span class="padding10"><strong>{{group.name}}</strong></span>
</li>
</ul>
</body>
and usergroups.new.html:
<body>
<form ng-submit="add()">
<input class="btn" type="submit" value="Add Usergroup"><br/><br/>
</form>
</body>
When I click on Add Usergroup, it will called add() from UsergroupsCtrl:
$scope.add = function() {
$scope.usergroups.push({name:$scope.name});
console.log($scope.usergroups);
}
The console show that $scope.usergroups is already updated. but somehow in usergroups.html: ng-repeat="group in usergroups" did not update the view. I add $scope.$apply() and $scope.$digest() but got an error:
$apply already in progress
But everything works fine if I did not use ui-router. How can I resolve this?
I think same $scope cannot be used in two different controllers. you can change it to $rootScope. like $rootScope.usergroups.push(). This SO may help you. You can use $stateParam also.
I am building a quick Angular app that uses a service to grab a JSON from a URL.
The JSON structure looks like this:
{news:[{title:"title",description:'decription'},
{title:"title",description:'decription'},
{title:"title",description:'decription'}
]};
What I need is just the array within the news object.
My code to import the JSON is as follows:
app.factory('getNews', ['$http', function($http) {
return $http.get('URL')
.success(function(data) {
return data;
})
.error(function(err) {
return err;
});
}]);
Then to add the data to the $scope object in the controller I do this:
app.controller('MainController', ['$scope','getNews', function($scope, getNews) {
getNews.success(function(data)) {
$scope.newsInfo = data.news;
});
});
But it doesn't work. When I load the html page, there is only white. My thinking is that this is because it isn't grabbing the array within the JSON and using that data to populate the HTML directive I set up.
newsInfo.js:
app.directive('newsInfo',function(){
return {
restrict: 'E',
scope: {
info: '='
},
templateUrl:'newsInfo.html'
};
});
newsInfo.html:
<h2>{{ info.title }}</h2>
<p>{{ info.published }}</p>
My HTML doc is:
<head>
<title></title>
<!--src for AngularJS library-->
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.3.5/angular.min.js"></script>
</head>
<body ng-app="THE APP NAME"> <!--insert ng app here-->
<div ng-controller="MainController"> <!--insert ng controller here-->
<div ng-repeat="news in newsInfo"><!--insert ng repeat here-->
<!-- directive goes here-->
<newsInfo info="news"></newsInfo>
</div>
</div>
<!-- Modules -->
<script src="app.js"></script>
<!-- Controllers -->
<script src="MainController.js"></script>
<!-- Services -->
<script src="getNews.js"></script>
<!-- Directives -->
<script src="newsInfo.js"></script>
</body>
Thoughts?
Change
<newsInfo info="news"></newsInfo>
to
<news-info info="news"></news-info>
example: https://jsfiddle.net/bhv0zvhw/3/
You haven't specified the controller.
<div ng-controller="MainController"> <!--insert ng controller here-->
<div ng-repeat="news in newsInfo"><!--insert ng repeat here-->
<!-- directive goes here-->
<newsInfo info="news"></newsInfo>
</div>
</div>
$scope.getNews = function(){
return $http.get('URL').success(function(data) {
return data.news;
})
};
^ This, just change it so that the success function returns only the news!
While I am answering my own question, I should point out that everyone's answers were also correct. The code had multiple errors, but the final error was fixed by doing the following:
Apparently I had to upload the newsInfo.html doc to an S3 bucket and use that URL as “Cross origin requests are only supported for HTTP.” But then Angular blocked that external source with the Error: "$sce:insecurl Processing of a Resource from Untrusted Source Blocked".
So since the html template was so simple, i just bipassed this issue by typing in the template directly into the .js directive and it worked! thanks everyone for the help!
I have something similar to this:
<div ng-controller="ControllerA">
<input type="text" id="search_form" value="Search" ng-model="searchModel" />
</div>
<div ng-controller="ControllerB">
<ul>
<li ng-repeat="item in items | filter:searchModel">{{item}}</li>
</ul>
</div>
But when I search in the input bar, it does not impact my list. How can I make my model from one controller impact the content of another?
Thanks.
Edit
ControllerA and ControllerB are entirely isolated of each other and I would like to keep it that way. If I need to share the model with the other controller, how would I use $rootScope to do that?
You can use a service to share data between controllers.
Use the factory feature which angular has to define the service.
Here is an example which i found here with and easy google search.
<!doctype html>
<html ng-app="project">
<head>
<title>Angular: Service example</title>
<script src="http://code.angularjs.org/angular-1.0.1.js"></script>
<script>
var projectModule = angular.module('project',[]);
projectModule.factory('theService', function() {
return {
thing : {
x : 100
}
};
});
function FirstCtrl($scope, theService) {
$scope.thing = theService.thing;
$scope.name = "First Controller";
}
function SecondCtrl($scope, theService) {
$scope.someThing = theService.thing;
$scope.name = "Second Controller!";
}
</script>
</head>
<body>
<div ng-controller="FirstCtrl">
<h2>{{name}}</h2>
<input ng-model="thing.x"/>
</div>
<div ng-controller="SecondCtrl">
<h2>{{name}}</h2>
<input ng-model="someThing.x"/>
</div>
</body>
</html>
if you have a model that needs to be shared you should use a service that way both controller can access the data and be aware of any changes