How import and use method from outer js-file into AngularJS? - javascript

I should like to use functional from this file https://ahunter.ru/js/min/ahunter_suggest.js
The documentation says that
1. import files
<head>
...
<script src="path_to_scripts/jquery.min.js"></script>
<script src="path_to_scripts/ahunter_suggest.js"></script>
...
</head>
Add id for input field
<div>
<input id="js-AddressField" placeholder="Введите адрес">
</div>
Add script
<script>
var options = { id : 'js-AddressField' };
AhunterSuggest.Address.Solid( options );
</script>
I added file to my project directory and added link into index.html, but i can't call
AhunterSuggest.Address.Solid( options ); in one of my controller.
How will do it right?

In your AngularJS controller, u have a method for initialising the controller right? If so, you have to call 3rd party library initialiser (3rd code in your message)
Make sure to call this, after dom is ready and angularJS controller initiated.
Your angular controller before (atm)
init() {
this.xxx()
}
Angular Controller after: (should be sth like this)
init() {
this.xxx()
this.initialiseAHunterSuggest()
}
initialiseAHunterSuggest() {
var options = { id : 'js-AddressField' }
AhunterSuggest.Address.Solid( options )
}

Related

Create a form container with Angular JS component

I am using Angular JS 1.5.6 and I would like to use only component and not directive.
I have more than 5 views using a form in my application. The style of the form is exactly the same in all the views, it is only the content of the form that changes. I have made components (input, button, etc..) and I would like to create a component for the form, it would be like a container component, in which I can put different components. In view A, the form will contain 1 button and 1 input, in view B the form will contain 2 button and 2 inputs, etc... But I don't know if it is possible to do it and how to dow it. I have plnkered this. I would like to create a component for the form.
<!DOCTYPE html>
<html ng-app="MyApp">
<head>
<link data-require="bootstrap-css#3.3.6" data-semver="3.3.6" rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.css" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.6/angular.min.js"></script>
<script src="script.js"></script>
<script src="myInput.js"></script>
<script src="myButton.js"></script>
</head>
<body ng-controller="MyCtrl">
<div class="container">
<h2>My form</h2>
<form role="form">
<my-input label="Firstname"></my-input>
<my-input label="Lastname"></my-input>
<my-button label="Submit"></my-button>
</form>
</div>
</body>
</html>
There are two basic problems need to be solved in your form container:
Dynamic template for your form
Handle summit should be run outside of your component.
I solve two problems by
Read template via attrs property
Pass handler function as a binding property
Code for form component:
angular.module('MyApp').component('myForm', {
templateUrl: function($element, $attrs) {
return $attrs.template; // read template file from component attribute
},
controller: MyFormController,
bindings: {
label: '#',
summitHandler: '&' // call to function outside of component via this property
}
});
In MyFormController, we need handle summit event by calling to summitHandler function passed via binding property:
function MyFormController($scope, $element, $attrs) {
var ctrl = this;
ctrl.summitForm = function(data) {
// call handler with data summited
var handler = ctrl.summitHandler();
handler(data);
}
}
That all for our form container component.
Now you can add my-form with:
<my-form label="Personal Info" template="myForm.html" summit-handler="ctrl.myFormHandler"></my-form>
Property ctrl.myFormHandler will be a function handling event in myCtl with:
ctrl.myFormHandler = function(data){
console.log('receive test summit:' + data);
ctrl.dataReceived = data;
}
See it run here in Plunk.
Typing in the age field, you can see it will be passed to outside of form. Extend it with more features as you want.
Look at this project:
http://kelp404.github.io/angular-form-builder/
If you want to implement this yourself you will need to create a template dynamically and compile it before it's injected into the DOM.
This project can be useful:
https://github.com/incuna/angular-bind-html-compile
It's directive but it will inject and compile your form elements (components or directives) for you:
<div bind-html-compile="formElements.input1"></div>

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.

Calling a function using AngularJS

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;
}
...

how to add ng-include callback to multiple ng-include directives in angular js

I have my HTML like this
<form ng-controller="testCtrl1">
<div ng-include="'test/views/navigationbar.html'"></div>
<div ng-include="'test/views/processnav.html'"></div>
<div ng-include="'test/views/leftprocesstabs.html'"></div>
</div>
</form>
I want to write generalized method to check all my ng-include file are loaded.
After loading all file i need to make a server call.
Is there any way to check this in angular js?
use the onload of each template and increment a counter.
if the form contains only ng-include divs, use the beow code to get the count, or write a function to get the count of divs with ng-include.
HTML
<form ng-controller="testCtrl1" id="includes">
<div ng-include="'test/views/navigationbar.html'" onload="load()"></div>
<div ng-include="'test/views/processnav.html'" onload="load()"></div>
<div ng-include="'test/views/leftprocesstabs.html'" onload="load()"></div>
</div>
</form>
Javascript
var templates = 0;
var length = $("#includes > div").length;
$scope.load = function(){
templates++;
if(templates >= length){
onLoadComplete()
}
}
function onLoadComplete(){
// all templates are loaded
}
ng-include triggers a request that goes through the template cache. This is done async so No, angular cannot provide you with a trigger for when all templates done loading.
You can prefetch the templates to the cache and handle the event from there ...
For example,
// inject $q, $http, $templateCache to your controller
...
var promises = [];
promises.push($http.get('test/views/navigationbar.html',{ cache : $templateCache }));
promises.push($http.get('test/views/processnav.html',{ cache : $templateCache }));
promises.push($http.get('test/views/leftprocesstabs.html',{ cache : $templateCache }));
$q.all(promises, function (data) {
console.log('All templates are loaded into the cache !');
});
...

Dynamically load/reload binding data on Ember Timeline

I am using the Ember Timetree code (Timetree) and I think it is great. I am a newbie to Ember and D3 so jumping into the Timetree code made my head hurt.
I am trying to add functionality so that if a user clicks a button on the page, the timetree will reload with different data. I have been trying for a while but nothing seems to work.
Here is what I have:
Ember template for the timetree:
<script type="text/x-handlebars" data-template-name="index">
<div class="example">
{{view Ember.Timetree.TimetreeView contentBinding="App.ApiData" selectionBinding="selectedEvents" rangeBinding="eventsRange_example2"}}
</div>
</script>
HTML that defines the timetree div:
<div id="app"></div>
HTML for the button the user clicks:
<button type="button" onclick="loadNewTimetree()">Reload</button>
Javascript for the function to reload the timetree:
function loadNewTimetree() {
var newJsonData = .... Get the JSON data
// Replace the existing JSON data with the newJsonData and re-draw the timeline - how?
}
What is the piece I am missing that links the updated JSON to timetree?
Thanks.
Marshall
I found the answer.
First, I added a viewName="mmView" tag to my Template:
<script type="text/x-handlebars" data-template-name="index">
<div class="example">
{{view Custom.Timetree.TimetreeView viewName="mmView" contentBinding="App.ApiData" selectionBinding="selectedEvents" rangeBinding="eventsRange_example2"}}
</div>
</script>
I found the core of the answer here. So I updated my javascript function:
function loadNewTimetree() {
var newJsonData = .... Get the JSON data
// View.views returns a hashtable. Key is the id, value if the View.
var views = Ember.View.views;
for (var nextKey in views) {
var nextView = views[nextKey];
// The 'viewName' is set in the template and needs to be unique for each timeline.
if (nextView.viewName && nextView.viewName == 'mmView')
{
nextView.reloadWithNewData(newJsonData );
}
}
}
Then I added a function in my View to handle the updated JSON:
Custom.Timetree.TimetreeView = Ember.Timetree.TimetreeView.extend(
{
... Other attributes,
reloadWithNewData:function (newTimelineJson)
{
// Need to clear out the svg contents before adding the new content
// or else you get strange behavior.
var thisSvg = this.get('svg');
thisSvg.text('');
this.set('content', newTimelineJson);
this.didInsertElement();
}
});
So when I call the loadNewTimetree() function, it updates the timeline with the new JSON.
The issue may be that you are not doing things the Ember way - which is very different but awesome. In Ember the button would typically be defined as
<button {{action 'loadNewTimeTree'}}>Reload</button>
and then in your view or controller one would have an action handler that would loadNewTimeTree. Typically by loading the data into an ember model.
App.IndexView = Ember.View.extend({
actions: {
loadNewTimeTree: function () {
var newJsonData = .... //Get the JSON data or more typical
this.get('controller.model').reload(); //typically JSON handled by RESTAdapter
}
}
});
If you want to learn the ember way which may be challenging I recommend studying their website

Categories

Resources