Angularjs: server side (php) rendering and data binding client side after an event
Asked Answered
I

2

5

The backend delivers a fully rendered site and on the frontend I want for angularjs to handle the dynamic content through ajax-call /data binding but if you deliver the directive ng-bind then angularjs binds them directly to their initial value which is NULL before any user action.

I found a hacky solution but I wanted to know if there is a better one or maybe another js framework that does exactly what I'm trying to do :

https://github.com/herschel666/angular-lazy-bind

the following example should help to understand my problem... once js is loaded the inital value "hola server side"(server side delivered) is gone. I want for the innerhtml/value to stay like that and keep the binding active but lazy so that it would only change it after an action the important thing is for angularjs to not rewrite what server side has already been writen(redered)

<html ng-app="myApp">
<head>
<meta charset="UTF-8">
<title>Title of the document</title>
</head>

<body >
<div ng-controller="GreetingController">
  <!-- this value has to stay ... but keep its binding property in order to change it afer an user action -->
  <span ng-bind="greeting"> hola server side</span>
  <button ng-click="update()">update</button>
</div>
</body>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.3.5/angular.min.js"></script>
<script type="text/javascript">
    var myApp = angular.module('myApp',[]);

myApp.controller('GreetingController', ['$scope', function($scope) {
  $scope.update = function (){
    //do ajax calls and set greeting and other data to bind
    $scope.greeting = 'Hola!';
  }
}]);
</script>
</html>
Insouciant answered 17/12, 2014 at 9:28 Comment(3)
The ngBind attribute tells Angular to replace the text content of the specified HTML element with the value of a given expression, and to update the text content when the value of that expression changes.Monitor
I know what ngBind does and that's exactly what I need to do, modify it's behavior or use some other method or other frameworkInsouciant
If I understand you correctly, wouldn't the solution be to set $scope.greeting to ' holy server side' at time of controller instantiation?Rameau
J
8

isomorphism

I wanted to know if there is a better one or maybe another js framework that does exactly what I'm trying to do

You are trying to build an isomorphic application. React will allow you to create isomorphic applications, but normally requires the backend be built in node.js. There is a way to use React with PHP. There are other solutions to isomorphism as well.

binding

the important thing is for angularjs to not rewrite what server side has already been writen(redered)

You can feed angular the server-side data by passing it in the HTML with a script tag, using the json_encode PHP function. This way angular will have the correct data when it starts up.

 <script>
  angular.module('app').constant('applicationData', <?= json_encode(application_data) ?>);
 </script>

Then you can inject applicationData and use it to initialize your directive. This approach is less than ideal because it forces you to deal with the same data twice. That's why using a view library like React which was built to support isomorphism is probably a better choice when creating an isomorphic application.

Johnie answered 23/12, 2014 at 4:51 Comment(0)
E
1

The Text: hola server side inside the Tag is useless, because it is replaced by Angular with the Content of Greeting. The Content of Greeting ist empty at start of the app.

Initialized of greeting in javascript

var myApp = angular.module('myApp',[]);
myApp.controller('GreetingController', ['$scope', function($scope) {
    $scope.greeting = "greeting initialized";
    $scope.update = function (){
          //do ajax calls and set greeting and other data to bind
        $scope.greeting = 'Hola!';
    }
}]);

complete example http://jsfiddle.net/ud6z4krk/5/

or

Initialize in greeting in HTML with ng-init

<div ng-app="myApp">
<div ng-controller="GreetingController">
  <span ng-init="greeting = 'hola server side'" ng-bind="greeting"></span>
  <button ng-click="update()">update</button>
</div>
</div>

complete example http://jsfiddle.net/ud6z4krk/8/

Or you make a new attribute-directive for your update-button. In the parameters of the directive you can reference to your content-tag. The directive add an Event to the update button to get the new Data from the server and update the contents of the referenced tag.

Expeditious answered 17/12, 2014 at 10:17 Comment(3)
1) opening the angular CDN link in a browser works perfectly fine for me. the leading double slash means 'protocol relative'. see #9646907 2) the fact, that "hola server side" is being replaced by angular is exactly the problem, which the question adresses. the desired initial value (in this case "hola server side") is already present, and it is annoying that angular would go and mess with it before any interaction has actually occured.Rhyner
unfortunately the updated solution doesn't work either, because if you disable JS (SEO/crawler point of view) then the span will be just empty, which is inacceptable. more importantly, with this approach, you will have a lot of JS action (causing a dom repaint/reflow) after the initial loading of the site, which is completely unnecessary because the desired initial values were already delivered by the server.Rhyner
Add a third solution that let the initial HTML content intact for search engines.Expeditious

© 2022 - 2024 — McMap. All rights reserved.