3

I need to load html from json file. So I found dform as best solution for that. Since it's the jQuery plugin and I need that in Angular. I am lucky that I found it's directive on jsfiddle.

The only difference is that I had my own json file and I have written the code separately. I am using service to get data from json file through http request. After that I am using the directive similar to the jsfiddle one.

app.js

var app = angular.module('angularApp', []);

service.js

app.service('loaderService', ['$http', function ($http) {
    this.getLoadedHtml = function (callback)
    {
        return $http.get('../source/file.json')
           .then(function (res) {
               callback(res.data);
           });
    }
}])

controller.js

app.controller('mainCtrl', ['$scope', 'loaderService', function ($scope, loaderService) {
    loaderService.getLoadedHtml(function (data) {
        $scope.fields = data;
    });
}]);

directive.js

app.directive('dform', function () {
    return {
        scope: {
            action: '@',
            method: '@',
            html: '='
        },
        link: function (scope, elm, attrs) {
            var config = {
                "action": scope.action,
                "method": scope.method,
                "html": scope.html
            };
            elm.dform(config);
        }
    };
})

index.html

<div class="container-fluid" ng-app="angularApp">
        <div ng-controller="mainCtrl" style="background-color:green; margin-top:100px; height:1000px;">
            <div class="col-sm-3" id="source-area">
                <div action="index.html" method="get" html="fields" dform></div>
            </div>
        </div>
    </div>

file.json

[
  {
    "type": "p",
    "html": "You must login"
  },
  {
    "name": "username",
    "id": "txt-username",
    "caption": "Username",
    "type": "text",
    "placeholder": "E.g. user@example.com"
  },
  {
    "name": "password",
    "caption": "Password",
    "type": "password"
  },
  {
    "type": "submit",
    "value": "Login"
  }
]

I have used jquery and dform library too.

Since I have not got any error. My array is coming fine into controller and $scope.fields is also working fine in controller. By I cannot see any html rendered? I have used the same as in jsfiddle.

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
CodeGenius
  • 514
  • 1
  • 6
  • 21
  • Approach of using jquery plugin makes no sense. What does json look like and what are expecped results from it. This should be easily achieved using angular templating and some data mapping – charlietfl Dec 25 '16 at 17:31
  • @charlietfl why is it running in jsfiddle? Question is that and why not it running in my code? – CodeGenius Dec 25 '16 at 17:32
  • But why are you even doing it this way in the first place? Strongly suggest you read http://stackoverflow.com/questions/14994391/thinking-in-angularjs-if-i-have-a-jquery-background – charlietfl Dec 25 '16 at 17:55
  • i know using Jquery with angular js is not a good practise. I am unable to find alternate of this plugin in angular. – CodeGenius Dec 25 '16 at 17:57
  • Although I agree with other commentators, for your specific problem, I bet the problem is that `elm.dform(config);` is running only once, it is not aware of html changes. So I would try to create a `$watch` on `html` property and in callback just call `elm.dform(config);` again. – Ilya Luzyanin Dec 25 '16 at 17:59
  • That being said, dform also supports loading forms from server, see [documentation](http://daffl.github.io/jquery.dform/#types/add-your-own), section "Or to quickly load an external form definition" – Ilya Luzyanin Dec 25 '16 at 18:01
  • @IlyaLuzyanin you are right, I am getting undefined in html field. in directive above this line: `elm.dform(config);` – CodeGenius Dec 25 '16 at 18:15
  • @IlyaLuzyanin can you please elaborate, I can feel you are right! :) – CodeGenius Dec 25 '16 at 18:21

1 Answers1

2

Elaborating on my comment. So what I think happens is dform does not reload automatically when the html changes (just not expecting it to change). What you could do in your directive is watch on html and update dform on change:

...
link: function (scope, elm, attrs) {
    var config = {
        "action": scope.action,
        "method": scope.method,
        "html": scope.html
    };

    scope.$watch('html', function() {
        elm.dform(config);
    });

    elm.dform(config);
}
...

But wait, there is more! As I mentioned, dform also supports loading external forms from server. According to documentation, that should be possible by using url subscriber. So your directive would look something like this:

app.directive('dform', function () {
  return {
    scope: {
        action: '@',
        method: '@',
        url: '='
    },
    link: function (scope, elm, attrs) {
        var config = {
            "action": scope.action,
            "method": scope.method,
            "url": scope.url
        };
        scope.$watch('url', function() {
          elm.dform(config);
        });

        elm.dform(config);
    }
  };
})

This eliminates the need in loader service. Now, I haven't tried this, so it maybe will require some tweaking from your side, by the idea should be clear by now.

UPDATE:

Ok, I've done a demo (which you should do next time you ask the question). The big problem was that the config.html needed to be reassigned after change in html property. So our link function now looks like this:

link: function(scope, elm, attrs) {
  scope.$watch('html', function() {
    if (!scope.html)
      return;
    var config = {
      "action": scope.action,
      "method": scope.method,
      "html": scope.html
    };

    $(elm).dform(config);
  });
}

P.S. I have replaced http call with timeout, but that makes absolutely no difference.

Ilya Luzyanin
  • 7,910
  • 4
  • 29
  • 49
  • Thanks for your time, I am in situation where I cannot load it from server directly. I have added watcher too but it gives me the same output that is nothing. Only I get in html is form tag and nothing inside. – CodeGenius Dec 26 '16 at 07:31
  • Can you console.log the new value In the `$watch` expression for html property? Are you sure you get the fields from server and they make it to the directive? – Ilya Luzyanin Dec 26 '16 at 10:42
  • I get nothing in html property, the workaround is that I need to get html from service again in directive's scope.`$watch`. I reassign new html and it works fine than. Is there any way through which I can get new value of `scope.fields` under `$watch` i.e. I need updated value for html in directive after it changes in controller? – CodeGenius Dec 26 '16 at 11:55
  • Please see updated answer. Now it should be very clear how to do it. – Ilya Luzyanin Dec 26 '16 at 17:32