Calling a function using AngularJS - javascript

I am working on application in AngularJs
Here is my code :
HTML
<div ng-controller="MainController as main" class="containerWrap">
..
..
..
<p ng-bind-html="parseMsg(msg)"></p>
..
..
The parseMsg function passes the msg filled by the user to the controller JS defined as follows :
this.parseMsg=function(msg){
...
...
if(msg['subtype']==FILES_UPLOADING){
$scope.showUploadOptions=true;
var per=parseInt(msg['text']);
if(per==100)
msg['text']='<div ng-if="showUploadOptions"><img ng-src="logo.png" ng-click="main.cancelFileUpload(chat,msg_id)"/></div>';
return $sce.trustAsHtml(msg['text']);
}
...
...
...
};
Chat and msg_id being passed to the main.cancelFileUpload are stored previously as:
$scope.chat = (object)
$scope.msg_id =(object)
this.cancelFileUpload=function(chat,msg_id){
alert("Cancel clicked ");
delete this.retryUploadFiles[msg_id];
delete chat.msgs[msg_id];
};
What I am trying to do is cancel the file upload being sent during the server request using a click on an image.
This ng-click is not responding. It doesn't give an error but doesn't function properly either.
Can anyone help identify the issues?
Thanks!

ngBindHtml don't compile your HTML. So, all angular directives from your dynamic HTML(ng-if, ng-src, ng-click, etc..) will not work.
To really compile your html you can use $compile service like that:
$compile(html)($scope)
But it's not a true way for angular. If you want to modify DOM structure - you need to use directives. In your case you can include that html to template itself instead of add it dynamically:
<div ng-show="showYourHtml">
<img ng-src="logo.png"
ng-click="main.cancelFileUpload(chat,msg_id)"/>
</div>
And your controler:
...
if(conditions){
$scope.showYourHtml = true;
}
...

Related

Laravel refresh data after ajax

He is currently working on code that has to filter the data in the table. Ajax will call the link and gets the response (json) results with answer. However, I came across a problem. I have to somehow render tables and I do not want to do this by append etc.
Can I somehow again generate views or blade file?
The default view is DefController#index but ajax use url which controller is DefController#gettabledata.
public function gettabledata($id){
return response()->json(Def::find($id)->getallmy->all());
}
You can put the part in your template corresponding to the table in a separate .blade.php file, and #include that in your main layout.
main.blade.php :
<html>
...
<body>
<div class="table-container">
#include('table')
</div>
</body>
...
And
table.blade.php:
<table>
#foreach($rows as $row)
<tr>
<td> $row->title ... </td>
</tr>
#endforeach
</table>
In this way you can use a simple jQuery $('div.table-container').load(url) and on your server just render and respond that part as an html string. return view('table', $data)
Javascript:
function refreshTable() {
$('div.table-container').fadeOut();
$('div.table-container').load(url, function() {
$('div.table-container').fadeIn();
});
}
The answer is yes, you can. Webinan certainly pointed you in the right direction. This approach is slightly different.
First things first, you need a seperate view for the table. A very basic example for the HTML markup:
<div class="table-container">
#include('partials.table') // this view will be async loaded
</div>
We start by making a call to the server with jQuery (can be done with Javascript too) using the shorthand ajax function: var $request = $.get('www.app.com/endpoint');. You can also pass along any data to your controller on the backend.
Now on the serverside, within your controller, render and return the table view:
class EndpointController extends Controller
{
/**
* Returns a rendered table view in JSON format.
*
* #param Request $request
* #return \Illuminate\Http\JsonResponse
*/
public function ajax(Request $request)
{
$html = view('partials.table', compact('view'))->render();
return response()->json(compact('html'));
}
}
If everything worked out, the done callback will be triggered. Simply grab the html variable and set it as the content of the table's container.
function renderTable() {
var $request = $.get('www.app.com/endpoint'); // make request
var $container = $('.table-container');
$container.addClass('loading'); // add loading class (optional)
$request.done(function(data) { // success
$container.html(data.html);
});
$request.always(function() {
$container.removeClass('loading');
});
}
Hope this helps!
To update and change page content without reloading the page in Laravel 5.4 i do the following:
First create the blade view in the "views" folder called "container.blade.php" it will contain the following code (in this case a select box that is rendering a list of abilities from the package Bouncer (but you can use the #foreach on any Laravel collection you like):
<select>
{{ $abilityList = Bouncer::role()::where('name','admin')->first()->getAbilities()->pluck('name') }}
#foreach ( $abilityList as $ab )
<option value="{{ $ab }}">{{ $ab }}</option>
#endforeach
</select>
Add this to you main blade file (e.g. home.blade.php) making sure to use a div with an id you can reference:
<div id="abilityListContainer">
#include('container')
</div>
Now on your main blade file (e.g. home.blade.php) add a button that will trigger the function that will communicate with the Laravel controller:
<input type="button" value="reload abilities" onClick="reloadAbilities()"></input>
Then add the javascript for this function, this loads the generated html into your div container (note the "/updateAbility" route next to ".get" - this is a Laravel route which we will set up in the next step):
var reloadAbilities = function()
{
var $request = $.get('/updateAbility', {value: "optional_variable"}, function(result)
{
//callback function once server has complete request
$('#abilityListContainer').html(result.html);
});
}
Now we set up the Laravel route for this action, this references our controller and calls the function "updateAbilityContainer". So edit your /routes/web/php file to have the following route:
Route::get('updateAbility', array('as'=> 'updateAbility', 'uses'=>'AbilityController#updateAbilityContainer'));
Finally in app/Http/Controllers make the file "abilityController.php" (you can also use "php artisan make:controller abilityController"). Now add this function to process the changes, generate the html and return it to the javascript function (note you may also have to use the namespaces as well):
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Input;
class AbilityController extends Controller
{
public function updateAbilityContainer()
{
// use this if you need to retrieve your variable
$request = Input::get('value');
//render and return the 'container' blade view
$html = view('container', compact('view'))->render();
return response()->json(compact('html'));
}
}
Thats it, your blade "container" will now reload when you click the button and any changes to the collection you are rendering should update without reloading the page.
Hopefully this fills in some blanks left in the other answers. I hope it works for you.

Dynamically add angular attributes to old html forms

I have a project where I'm currently trying to refactor an old system that was hinged on jquery from the ground up with angular 1.x. However, there are a lot of old HTML forms that I'd like to reuse the bulk of so I don't want to recreate them. I'd love it if there was a way to keep it purely angular, but I'm honestly at a loss of how I'd do that (or whether or not I can). I'm fairly new to angular so there are a lot of inner workings to it that I'm still not privy to.
I've searched around on google and other places including here and I can't really even find other people talking about it. That tells me that either I'm searching badly or it's something that I should probably not be working towards.
All the html pages have identically id'd fields so I feel I can reliably base things on that. For example: all forms with first name text boxes have an id of "cl_fname".
Is there anyway that I can accomplish: getting the form, adding an ng-model="cl_fname" or something to the relevant tag and then display the form? I've gotten to the point where I can get the html page, hold it in the scope and then display using ng-bind-html, but figuring out how to add angular attributes to specific elements I can't figure out.
You can achieve this with jQuery and the attr() method.
I created a plunker here that demonstrates adding angular to an existing "plain" html form.
In the example, I'm using id selectors, but you could use any combination of selectors to ensure you get the right elements.
The below is a quick code snippet from my Plunker example:
HTML:
<div ng-app="myApp">
<form id='myForm1' data-test="test2">
<span>First Name:</span>
<input type="text" id="myForm1_firstName" />
<input type="submit" id="myForm1_Submit" value="Go!" />
</form>
</div>
JS:
// set up angular
var myApp = angular.module('myApp', []);
myApp.controller('MyForm1Controller', ['$scope', function($scope) {
$scope.firstName = 'Angular Working!';
}]);
// use jQuery to add the relevent attributes to our form
var jqMyForm1 = $('form#myForm1');
var jqTxtFirstName = jqMyForm1.find('input[type="text"]#myForm1_firstName');
//add controller to form
jqMyForm1.attr('ng-controller', 'MyForm1Controller');
//bind the textbox to the angular 'firstName' variable
jqTxtFirstName.attr('ng-model', "firstName");
EDIT:
just realised you want to load the html form dynamically.
Version 2 of the plunker (here) will now dynamically load a HTML form from an external resource (separate html page), inject it into the current page, add the angular bindings to it, and then get angular to recognise it.
The key to getting angular to recognise the form is the use of the $compile object (angular $compile documentation).
Again, quick snippets of the code in use:
HTML (main page):
<div ng-app="myApp" ng-controller="LoadingController"></div>
HTML (myForm1.html):
<form id='myForm1' data-test="test2">
<span>First Name:</span>
<input type="text" id="myForm1_firstName" />
<input type="submit" id="myForm1_Submit" value="Go!" />
</form>
JS:
// set up angular
var myApp = angular.module('myApp', []);
// main controller for loading the dynamic form
myApp.controller('LoadingController', ['$scope','$http','$compile', function($scope,$http,$compile) {
$scope.loadHtmlForm = function(formURL) {
$http.get(formURL).then(function successCallback(response){
var jqForm = $(response.data);
var jqTxtFirstName = jqForm.find('input[type="text"]#myForm1_firstName');
//add controller to form
jqForm.attr('ng-controller', 'MyForm1Controller');
//bind the textbox to the angular 'firstName' variable
jqTxtFirstName.attr('ng-model', "firstName");
$('div').append(jqForm);
$compile(jqForm[0])($scope);
});
}
$scope.loadHtmlForm('myForm1.html');
}]);
// form controller for managing the data
myApp.controller('MyForm1Controller', ['$scope', function($scope) {
$scope.firstName = 'Angular Working!';
}]);

Binding Controller Property containing HTML in AngularJS

First of all: I am absolutely new to AngularJS but worked on MVC-projects in other languages.
I try to bind a Property containing HTML.
This is the code:
HTML:
<div ng-controller="MyController">
<p>{{About}}</p>
</div>
JS:
.controller('MyController', ['$scope', function($scope) {
$scope.About="This is me<br/>and not you!"
}
Now the HTML is encoded which I do not want (the <br/> should result in line breaks)
I already tried <p ng-bind-html="About"></p> but that resulted in no output at all
You need to allow html in your text which Angular does not by default.
Plunker: http://plnkr.co/edit/K4KRCQi4Rpe99MJel5J2?p=preview
Angular Docs for $sce
Strict Contextual Escaping (SCE) is a mode in which AngularJS requires
bindings in certain contexts to result in a value that is marked as
safe to use for that context. One example of such a context is binding
arbitrary html controlled by the user via ng-bind-html. We refer to
these contexts as privileged or SCE contexts.
<div ng-controller="htmlChar" ng-bind-html="about"></div>
<script>
angular.module("app",[])
.controller("htmlChar",function($scope, $sce){
$scope.about= $sce.trustAsHtml("This is me<br/>and not you!");
});
angular.bootstrap(document,["app"]);
</script>
You shoudln't need to insert html through model binding in AngularJS since the philosophy of the framework is to keep the HTML (page's structure and style) intact and only bind the data to be shown inside that HTML.
If you really need to bind HTML tags into your data you need to use the $sanitize service.
You have to use angular compile functionality here, go through the link to get more information angular compile

ng-click doesn't take parameters from the DOM

I have the following code:
<input id="id">
<button data-action="bea" ng-click="Create($('#id1')[0].value);" class="btn">Insert ID</button>
<button data-action="bea" ng-click="Create($('#id2')[0].value);" class="btn">Insert ID</button>
In the JS I have:
$scope.Create = function (id){
if (id === undefined) {
$scope.data = "You must specify an id";
} else {
$scope.data = data;
console.log(data);
});
}
};
When the call gets into the Create function the value of the id is undefined.
If I add the following line at the beginging of the Create function everything works ok:
id = $('#id')[0].value;
If I send a constant value it works:
<button data-action="bea" ng-click="Create('SomeID');" class="btn">Insert ID</button>
Why is this happening and how can I do that without putting the line of value into the method?
Thanks
This is just an extension of comments and other answers, You could achieve this in many ways using angular, one simple example could be:-
<!-- Add a controller -->
<div ng-controller="MainCtrl">
<!-- Give a model binding to your text input -->
<input ng-model="userEntry" type="text"/>
<!-- ng-click pass which ever argument you need to pass, provided it is an expression that can be evaluated against the scope or any constants -->
<button data-action="bea" ng-click="Create(userEntry);" class="btn">Insert ID</button>
<!-- Some simple data binding using interpolation -->
{{data}}
<!-- Just for demo on repeater on a list of items on the scope -->
<div ng-repeat="item in items track by $index">{{item}}</div>
</div>
Example Demo
My 2 cents on the lines of what were originally trying to do:-
Use angular bindings instead of accessing DOM directly for getting the data, it really helps you deal with just the data without worrying about how to access or render it in DOM. If you think you need to access DOM for implementing business logic re-think on the design, if you really need to do it, do it in a directive. Angular is very opinionated on the design and when where you do DOM access.
ng-model
ng-binding
controller
all about ngmodel controller
This is not the way you should do in AngularJS. You should really think in Angular if you want to use AngularJS. Refer this post ("Thinking in AngularJS" if I have a jQuery background?)
All DOM manipulation should be done in Directive. Refer this page that I found really clear.
(http://ng-learn.org/2014/01/Dom-Manipulations/)
My guess is that $ is not bound to the jQuery function when the ng-click value is evaluated, because it is not exposed in the Angular scope.
Solutions to adress this:
expose the jQuery function in scope somewhere, e.g $scope.$ = $; in a controller.
make the Create function parameterless as you suggested, with a var id = $('#id')[0].value; at the beginning
my favorite : avoid using jQuery. If you put some data in the #id element, there's probably a more natural and AngularJS-idiomatic way of retrieving it than querying the DOM (e.g an Angular service).
In particular, if the element you're targeting is an <input> element, then use the ngModel directive to link the value to a $scopeproperty that will be accessible in the controller :
<input ng-model="inputData"/>
The JavaScript you are trying to pass as a parameter of the create function is not available in the scope of the Create function.
Try to target the element a different way.
Does that help?

AngularJS changing controller parameter

I have been ploughing into AngularJS and am trying to get my head around how everything links together but I've become a bit stuck.
How can I pass a variable to change the JSON that is loaded and shown on the page?
I thought it would be a button click and the directive would talk to the controller, but how I'm not so sure.
If i have my JSON as something like this as in controller...
var id = 'peter';
var person = $resource('http://myjson.com/'+id+'.json')
I can't figure out how I would change the id based on button clicks for example.
Any help is greatly appreciated
I'll try to explain as simple as possible, you can pass data as argument to a function from HTML to controller using the ngClick directive.
The function inside the controller will be invoked because it has a binding to the ngClick directive using the $scope.
Example:
html:
<div ng-app="App" ng-controller="ctrl">
<div ng-repeat="itemId in items">
<button ng-click="myClickFunc(itemId)">click {{itemId}}</button>
</div>
</div>
js:
var app=angular.module('App', ['ngResource']);
function ctrl($scope,$resource){
$scope.items=[1,2,3,4];
$scope.myClickFunc=function(itemId){
var person = $resource('http://myjson.com/get/:id');
person.get({id: itemId}).$promise.then(function(data) {
// success
$scope.myData = data;
}, function(errResponse) {
// fail
});
}
Live example: http://jsfiddle.net/choroshin/zJ5G6/

Categories

Resources