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>
Related
I am working with an MVC Entity Framework Webapp. I have a view that displays other partial views that are updated every 30 seconds. The issue is the dynamic progress bar I am using does not fill up at all and I have tried everything I know. The problem I think is the css that gets passed to the partial view ("width", current_progress + "%"). Here is a pic and the bar is supposed to be over half full...
Controller methods:
public ActionResult Dashboard()
{
ViewBag.SumofDon = db.tblDonors.Sum(s => s.DonationAmount);
return View(db.tblDonors.ToList());
}
public ActionResult Progress()
{
return PartialView("_Progress", db.tblDonors.ToList());
}
Dashboard.cshtml:
#model IEnumerable<bssp.Models.tblDonor>
#{
ViewBag.Title = "Dashboard";
}
#section Scripts{
<script>
function loadProgressPV() {
$.ajax({
url: "#Url.Action("Progress")",
type: 'GET', // <-- make a async request by GET
dataType: 'html', // <-- to expect an html response
success: function(result) {
$('#progress').html(result);
}
});
}
$(function() {
loadProgressPV(); // first time
// re-call the functions each 10 seconds
window.setInterval("loadProgressPV()", 10000);
});
</script>
<script>
$(function () {
var SumofDon = #ViewBag.SumofDon;
var current_progress = (SumofDon / 20000) * 100; // 20000 is the goal that can be changed
$("#dynamic")
.css("width", current_progress + "%") //This causes the problem?
});
</script>
}
<div class="container-fluid">
<div class="row" id="progress">
#Html.Partial("_Progress")
</div>
</div>
Partial view:
#model IEnumerable<bssp.Models.tblDonor>
<div class="row">
<br /><br /><br />
<div class="col-md-12">
<div class="well bs-component">
<h4>#String.Format("{0:C}", #ViewBag.SumofDon) out of $20,000<br /></h4>
<div class="progress progress-striped active">
<div class="progress-bar" id="dynamic" style="width: 0%"></div> #*The width is what gets updated because it found the id of dynamic*#
</div>
</div>
</div>
</div>
Any help would be awesome and thanks in advance!
I think your issue is that you pull in the html from the partial with a style="width: 0%" but then jQuery that adjusts the css, $("#dynamic").css("width", current_progress + "%"), is only run on page load, not after the partial reloads. You have two options to fix this,
Run the jQuery function after the razor loads in from the partial, in the success method of the ajax.
Since you are using razor to create the partial, why not just do the calculation right there? That way the partial comes in already set up with the width set. This is the easier and faster option of the two.
I thought this should be something easy because I've done it before, but apparently the first time I got lucky, either that or Angular has some quirks I have not yet wrapped my head around.
What I'm trying to do is be able to edit a customer order. All customer orders are sent to the client from the database as JavaScript objects, using PHP.
That is fine, my problem is within Angular when I want to edit these orders, through a modal window (which has its own scope). Basically a form pops up in the modal that asks the user to edit the Javascript object, of course however no user wants to edit a raw object so it's a form with ng-models tied to that object. My problem is the ng-model doesn't seem to pick up my object reference.
So here we go (I have a plunker below):
This is the controller that fetches the customer order on the page the first time (before the user initiates the modal to edit the order):
controller: function($scope,$http,$stateParams,$uibModal) {
$http({
method: 'GET',
url: 'http://example.com/orderDATA',
params: {id: $stateParams.id}
}).then(function successCallback(html) {
html.data[0].orderProperties = JSON.parse(html.data[0].orderProperties); //format data from server so that JavaScript can play with it
$scope.order = html.data[0];
$scope.edit = function (order) //function that launches modal window
{
var modalInstance = $uibModal.open({
animation: $scope.animationsEnabled,
templateUrl: 'EditOrderInstance.html',
controller: 'EditOrderCtrl',
scope: $scope,
size: "lg",
resolve: {
order: function() {
return order;
}}
});
}
});
}
The edit() function is called like so from the following template:
<div class="container" style="margin-top:2%;">
<div class="row">
<div class="col-xs-12" style="text-align:center;">
<p class="whiteNoPointy">Customer Name : #{{order.orderProperties.firstName + " " + order.orderProperties.lastName}}</p>
</div>
<div class="col-xs-12" style="text-align:center;">
<p class="whiteNoPointy">Pickup : #{{order.orderProperties.pickupDate + " in " + order.orderProperties.location}}</p>
</div>
<div class="col-xs-12" style="text-align:center;">
<p class="whiteNoPointy"><i class="fa fa-envelope" aria-hidden="true"></i> : #{{order.orderProperties.email}}</p>
</div>
<div class="col-xs-12" style="text-align:center;">
<p class="whiteNoPointy"><i class="fa fa-phone" aria-hidden="true"></i> : #{{order.orderProperties.phone}}</p>
</div>
<div class="col-xs-12" style="text-align:center;">
<button type="button" style="border-radius:0;" class="btn btn-warning" ng-click="edit(order)">Edit This Order</button> <button type="button" style="border-radius:0;" class="btn btn-danger">Delete or Refund This Order</button> <button type="button" style="border-radius:0;" class="btn btn-primary">Complete This Order</button>
</div>
</div>
</br></br>
<div class="shipping whiteNoPointy text-center" ng-repeat="specific in order.order">
<div class="col-xs-12" ng-if="specific.quantity.value>0"><p>#{{specific.quantity.value}} #{{specific.Name}}</p></div>
</div></div>
This part works fine. However, when I do hit the edit function, that takes us into a new scope and a new controller, specifically the one below:
app.controller('EditOrderCtrl', ['$scope', '$http', '$uibModal','$uibModalInstance', 'order', function($scope, $http, $uibModal, $uibModalInstance, order) {
$scope.order = order;
So as is hopefully clear, all I did was pass the order object to the modal.
Now to me, all I've done is pass the same order object around, and now to this new controller. But the problem is that when I investigate this latest order it has no $$hashkey. I say this because of the problem that follows, as I said I did this before except in that instance I passed the order object from inside an ng-repeat, and the last step worked. But here when I do it it doesn't work.
What I mean is, when I try to have the models in the modal template line up with the order object passed to the modal's controller, they don't. I just get blank inputs, which isn't good because to edit a customer order you need to now what the current order is, otherwise it's like you are starting over.
Here is the template with the ng-model.
<script type="text/ng-template" id="EditOrderInstance.html">
<div class="modal-header" style="text-align:center;">
<h3 class="modal-title">Edit Order</h3>
</div>
<div class="modal-body" style="text-align:center;">
<form name="order" novalidate>
<label for="firstName">First Name</label>
<input type="text" name="firstName" class="form-control" ng-model="order.orderProperties.firstName" ng-minlength="2" required>
<p ng-show="orderorderProperties.firstName.$error.minlength" class="warning">Please put your full first name.</p>
</div>
<button ng-disabled="order.$invalid||totalPrice===0" ng-click="submitOrder()" class="btn btn-default">Submit</button>
</form>
</div>
<div class="modal-footer" style="text-align:center;">
<button class="btn toggledz" type="button" ng-click="save()">Submit</button>
<button class="btn" type="button" ng-click="cancel()">Cancel</button>
</div>
</script>
Notice the order.orderProperties.firstName ng-model. This is there, I console log it from the modal's controller and I can see it is set, but the model is blank. So why is this the case? Why did it work before when the console.log() showed the object was passed with a $$hashkey? I can't pass from an ng-repeat again because I only have one order, so there is nothing to iterate over in the first template.
Please assist. I need to be able to edit the order using ng-model, so that the admin can edit the order and send a new order object back to my server.
Edit: Added a plunker: https://plnkr.co/edit/x6FPiS6OtF2gdn4ZtFyJ?p=preview
From the first look, the problem appears to be with your resolve function
controller: function($scope,$http,$stateParams,$uibModal) {
$http({
method: 'GET',
url: 'http://example.com/orderDATA',
params: {id: $stateParams.id}
}).then(function successCallback(html) {
html.data[0].orderProperties = JSON.parse(html.data[0].orderProperties); //format data from server so that JavaScript can play with it
$scope.order = html.data[0];
$scope.edit = function (order) //function that launches modal window
{
var modalInstance = $uibModal.open({
animation: $scope.animationsEnabled,
templateUrl: 'EditOrderInstance.html',
controller: 'EditOrderCtrl',
scope: $scope,
size: "lg",
resolve: {
order: function() {
return $scope.order;
}}
});
}
});
}
Your resolve function for order should return $scope.order
Try it and let me know if this works. I am just going with the instincts
I got it to work by changing the variable name, I guess for some reason it was looking to the old $scope.order instead of the one resolved to the modal?
Anyway, here is a working plunker...
https://plnkr.co/edit/AZpeFGaBktFjSr2SL2Rv?p=preview
I have the following code in my html.
<div id="section">
<div new-exercise ng-repeat="section in sections track by $index">
</div>
</div>
<div class="add_exercise add_exercise_btn">
<a class="add_exercise_link" ng-click="addExercise()">
<span>+ Add an Exercise</span>
</a>
</div>
the method addExercise() adds a new element to the variable sections, hence updating the html with another template (represented by directive new-exercise).
i.e.
$scope.addExercise = function(){
$scope.sections.push({
title: "hello",
content: "fsa"
});
}
The directive new-exercise:
.directive('newExercise', function () {
return {
templateUrl: '/templates/exercise-form.html',
replace: true,
}
})
The template exercise-form.html:
<div class="add_exercise" id="add_exercise_form" data-section-id="{{id}}">
<form class="new_section">
<div class="input-box">
<input id="title" type="text" name="title" class="form-control" value="{{section.title}}" ng-model="section.title">
<label for="title">Exercise Name</label>
<span class="help-block"></span>
<span>{{ section.title }}</span>
</div>
</form>
</div>
I expect the template exercise-form.html to update the value inside input to be hello but the scope is empty.
However, if I remove the directive and add the template html under ng-repeat it works as I expect. I feel that the scope is lost due to directive, but not so sure about the exact reason. Can anyone explain me the reason and how to resolve?
Thanks.
Remove the replace: true in your directive.
Corrected directive given below:
.directive('newExercise', function () {
return {
templateUrl: '/templates/exercise-form.html'
}
})
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 ?
I know it might be a simple question, but I'm frustrated here, and I can't make it work. I'm new to AngularJS, and I'm trying to implement a modal dialog (or find one) with these conditions:
Dialog content might come from anywhere—a string template, a script template, or a template from a URL
Dialog title and actions will come from the caller, not the callee. In other words, the parent scope decides the title and which action buttons should exist in the modal dialog (many dialogs I found encapsulate the title and action buttons in the template itself, for example this one)
Content of the template should be totally independent from parent scope (caller). In fact, it might not even be written in AngularJS. It might use jQuery.
In case the loaded template is in AngularJS, it should encapsulate its controller. For example, ng-include doesn't like <script> tags.
There is a workaround for it (here, here and here) but the idea of decorating a script tag with text/javascript-lazy is very smelly and dirty, let alone that I want the content HTML to be self-contained and executable in case it's not loaded as the content of an AngularJS modal dialog.
Communication between the parent scope and the content should be done via a common contract (JavaScript events come to my mind)
I've tried ngDialog, but the problem is that the container should pass the controller to the loaded template. That's not what I want.
In Bootstrap dialog also it seems that you have to pass the controller from the parent scope to the dialog content. This breaks the very notion of encapsulation. It's not desirable. Also, it's dependent on dialog result, which is not desirable either.
I recommend use Angular-UI library. You can easy create any dialog a-la "Twitter Bootstrap":
Include js in your page head.
<script src="/desktop/libs/angular-bootstrap/ui-bootstrap.js"></script>
<script src="/desktop/libs/angular-bootstrap/ui-bootstrap-tpls.js}"></script>
Include modules at app initialization.
var Application = A.module('MyApp', [ 'ui.bootstrap', 'ui.bootstrap.modal' ]);
Inject in jour controller $modal:
(function (A){
"use strict";
A.module("MyApp").controller("OpenDlg", [ "$scope", "$modal", function($scope, $modal){
$scope.openDlg = function(){
$modal.open({
controller : 'CategoryAddController',
templateUrl : '/admindesktop/templates/category/add/'
}).result.then(function(modalResult){
console.log(modalResult);
});
};
} ]);
}(this.angular));
For example, simple template for dialog:
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title text-center">Создание новой категории</h4>
</div>
<form class="modal-body form-horizontal" name="categoryForm">
<div class="form-group">
<label for="name" class="control-label col-xs-3">Название</label>
<div class="col-xs-9">
<input name='name' type="text" class="form-control" ng-model="category.name" maxlength=50 required ng-required="true"/>
</div>
<div class="row has-error" ng-show="errors.name">
<p ng-repeat="error in errors.name">{{ error }}</p>
</div>
</div>
<div class="container-fluid" ng-show="errors.length > 0">
<div class="row">
<p class="text-center text-danger" ng-repeat="error in errors">{{ error }}</p>
</div>
</div>
</form>
<div class="modal-footer">
<button class="btn btn-primary" ng-click="save()" ng-disabled="categoryForm.$invalid">Сохранить</button>
<button class="btn btn-default" ng-click="cancel()">Отмена</button>
</div>
</div>
Main: controller for modal window:
(function(A) {
"use strict";
var app = A.module('MyApp');
app.controller('CategoryAddController', [ '$scope', '$modalInstance', 'Category', 'growl', function($scope, $modalInstance, Category, growl) {
$scope.save = function() {
var category = new Category($scope.category);
category.$save(function() {
growl.success('Категория успешно создана');
$modalInstance.close(true);
}, function(response) {
$scope.errors = response.data;
});
};
$scope.cancel = function() {
$modalInstance.close(false);
};
} ]);
}(this.angular));
I use Service for data changing between modal controller and parent scope:
(function(A){
"use strict";
A.module("MyApp").service('Storage', function(){
return {
storedData: undefined
};
});
}(this.angular));
In parent scope:
Storage.storedData = ...; //For example, selected row of table
In modal controller:
$scope.item = Storage.storedData; //Selected row of table
Also angular have special module type, value.